制作了一个递归函数,该函数给出给定起始编号的collatz序列中有多少个术语,例如:代码n = 13:
int collatz(long n,long o)
{
if (n!=1) {
if(n%2==0)
return collatz(n/2,o+1);
else
return collatz((n*3)+1,o+1);
} else
printf("%ld\t",o);
}
void main()
{
collatz(13,0);
}
函数按预期运行;但是,对于某些整数,例如“ n = 113383”,某些东西会溢出(我想)并返回:
Process returned -1073741571 (0xC00000FD) execution time : 4.631 s
Press any key to continue.
不好意思,非常感谢!
答案 0 :(得分:3)
C标准本身对递归深度没有限制。您可能会导致堆栈溢出,但是在不同的环境中堆栈大小会有所不同。我认为Windows有1MB,Linux有8MB。它还取决于函数的堆栈框架的大小,而堆栈的大小又取决于函数具有多少变量和哪种类型。
在您的情况下,您有两个long
变量,每个变量可能是8个字节。您还有一个字符串"%ld\t"
,它是5个字节,可能会在堆栈上结束,但是我不确定。最重要的是,您有两个指向函数返回地址和前一个堆栈帧的指针的开销,在64位系统上,它们分别为8个字节。因此,函数的堆栈帧大约为32个字节左右。也许更多。因此,在Linux系统上,我猜想您的功能将在大约20万的深度崩溃。
如果这是一个问题,请考虑将函数重写为非递归变量。查看Blaze的答案,以了解如何针对您的案例。正如安德烈(Andreee)在下面的评论:
附加说明:您可以在Linux下使用ulimit -s增加堆栈大小(也可以:ulimit -s unlimited),而在MSVC中,可以设置/ F编译标志来增加程序的堆栈大小。对于MinGW,请参阅this帖子。
答案 1 :(得分:2)
这里发生的是堆栈溢出。发生这种情况是因为每次调用该函数都会创建一个新的堆栈帧,并且如果堆栈帧过多,则堆栈的内存将用完。您可以使用迭代而不是递归来解决它。
此外,long
可能无法保存collatz序列为起始值113383
生成的数字(对于MSVC而言,这不是我的意思)。请改用long long
,该大小至少为64位。总而言之,它可能像这样:
void collatz(long long n)
{
long o;
for (o = 0; n > 1; o++) {
if (n % 2 == 0)
n /= 2;
else
n = n * 3 + 1;
}
printf("%ld\t", o);
return;
}
int main()
{
collatz(113383);
return 0;
}
请注意,现在我们有了for
循环而不是递归了。