0

答案可能是显而易见的,但对于我的生活,我看不到它。我试图找出用户提供的正整数收敛到 1 需要多少次迭代(即递归函数是 f(x)=x/2 如果 x 偶数,3x+1 如果 x 奇数)。如果使用蛮力(即通过一系列 if 语句),答案是微不足道的。然而,我的目标是采用递归方法,并陷入无限循环:

#include <stdio.h>

int collatz(long number, int length)    
{

    while (number != 1)
    {
        length++;
        printf("%ld\n", number);
        if ((number % 2) == 0)
            collatz(number/2,length);
        else
            collatz(3*number+1,length);
    }

    return length;
}
int main()  
{
    long number;
    printf("Input a number\n");
    scanf("%ld", &number);
    int length=1;
    printf("length is %d", collatz(number,length));
    return 0;
}

当 number=1 时会出现问题。它没有终止循环,而是继续,因此它无限期地在 1 和 2 之间振荡。

4

3 回答 3

3

该语句while (number != 1)永远不会评估为假,因此无论何时通过,您都会陷入无限循环number != 1

至于计算“长度”,您是通过值传递的,因此该函数不会计算达到 1 所需的 Collat​​z 迭代次数。相反,只需返回 1 加上 Collat​​z 迭代次数的适当继任者数字。例如,一个数字所需的 Collat​​z 迭代次数n是 1 加上适当的递归调用返回的数字,或者n/23*n+1,分别取决于n是偶数还是奇数。

这将起作用:

int collatz(long number)    
{
    if (number != 1)
    {
        printf("%ld\n", number);
        if ((number % 2) == 0)
            return 1+collatz(number/2);
        else
            return 1+collatz(3*number+1);
    }

    return 0;
}
于 2016-05-06T09:10:39.233 回答
0

我同意@blazs。请注意,在 while 循环中,您实际上并未修改变量编号,因此当递归回滚到调用者函数时,while 循环将再次评估变量编号的本地副本(未更改),然后 while 循环将保持永远走下去。。

于 2016-05-06T09:48:44.380 回答
0

这也有效,解决了将变量副本传递给函数的范围问题:

    #include <stdio.h>

int collatz(long number, int length)    
{
    int temp=number;    
    int templength=length;  
    while (temp!= 1)
    {
        templength++;
        printf("%ld\n", number);
        if ((temp% 2) == 0)
            return collatz(temp/2,templength);
        else
            return collatz(3*temp+1,templength);
    }

    return templength;
}
int main()  
{
    long number;
    printf("Input a number\n");
    scanf("%ld", &number);
    int length=1;
    printf("length is %d", collatz(number,length));
    return 0;
}
于 2016-05-16T05:18:42.350 回答