我正在使用VC ++ 2010.我编写了一个简短的程序,以便在长整数数组中获得100万个数字的Collatz猜想链,并获得最高的数字序列。当我尝试运行代码时,我得到堆栈溢出异常。
我应该如何解决这个问题?
//Might have took un-needed headers
#include "stdafx.h"
#include "stdio.h"
#include "conio.h"
#include "iostream"
#include "fstream"
#include "string"
#include "list"
using namespace std;
//traverse the array for max term
long int max_array(long int a[], long int num_elements)
{
long int i, max=-32000;
for (i=0; i<num_elements; i++)
{
if (a[i]>max)
{
max=a[i];
}
}
return(max);
}
//recursive function to calculate and count based on Collatz_conjecture
long int Collatz( long int c1, long int currentcounter)
{
if ( c1 == 1) return currentcounter;
if ( c1 % 2 ==0)
{
currentcounter++;
Collatz (c1/2, currentcounter);
}
else
{
currentcounter++;
Collatz((3*c1)+1, currentcounter);
}
}
void main()
{
long int totalcounter[1000000]={0},t1,max;
for (long int i=1;i<1000001;i++)
{
totalcounter[i]++;
totalcounter[i]=Collatz(i,totalcounter[i]);
printf("Collatz count of no: %li is %li \n",i,totalcounter[i]);
}
max = max_array(totalcounter, 1000000);
printf("The max is %d\n", max);
}
答案 0 :(得分:3)
堆栈内存由自动变量和递归函数调用消耗。你使用大量的两者。
您可以使用迭代(Way to go from recursion to iteration)替换递归,并且可以使用堆分配的自变量(巨型数组)替换(使用new
)。
这两件事都应该对你有所帮助。只需确保当你使用堆积分配堆栈的Collatz功能的迭代方法时,你就不会再遇到同样的问题了!
答案 1 :(得分:2)
堆栈通常是固定的,相当小的大小 - 可能是几兆字节。您正在做两件容易导致堆栈使用过多的事情:
第一个可以通过使用计数器的动态数组来修复:
std::vector<long int> totalcounter;
或者不存储所有结果,只是每次迭代后找到的最大结果。
第二个可以通过检查编译器是否优化递归或者迭代实现来修复;这样的事情(未经测试):
long int Collatz(long int c1)
{
long int counter = 0;
while (c1 != 1) {
++counter;
c1 = (c1 % 2 == 0) ? c1/2 : 3*c1+1;
}
return counter;
}
(如果您决定保留递归实现,那么您需要通过引用传递currentcounter
,或者使用每个递归调用的返回值更新它,并记住在所有情况下都返回一个值此外,main()
中的数组索引应该从0
运行到N-1
,而不是从1
到N
。main()
必须返回{ {1}},但如果您愿意,可以省略int
语句。
答案 2 :(得分:1)
在为大量数字计算Collatz链时,你会溢出long int
。我认为这就是你的递归函数出错的原因。尝试将c1
参数更改为64位类型,例如long long
。
我刚试过这个,当你达到值704511时,链的范围高达56991483520.顺便说一下,这是Project Euler问题14。
编辑:
将数组totalcounter[]
的声明移到main()
函数之外,使其成为全局变量。对于堆栈上的自动存储来说,它太大了(~4MB)。其他替代方案是动态分配数组或使用std::vector
。
您的代码工作示例here。