为什么我不能在C++中使用这段代码?
#include <iostream>
#include <time.h>
using namespace std;
int main()
{
const int number = 1000000;
//Chain Vars-------------------
int chainLength = 0;
int startingNumber = 0;
int chain = 0;
int n = 0;
//----------------------------
// start Time-----------------
clock_t startTime = clock();
double duration;
//---------------------------
//Cache-----------------------------
int* cache = new int[number+1];
for (int i = 0; i < number+1; i++)
{
cache[i] = -1;
}
cache[1] = 1;
//---------------------------------
for (int i = 2; i <= 1000000; i++)
{
n = i;
chain = 0;
while (n != 1 && n >= i)
{
chain++;
if ((n % 2) == 0)
{
n = n/2;
}
else
{
n = n * 3 + 1;
}
}
//Store the chain length in cache
cache[i] = chain + cache[n];
//-------------------------------
if (cache[i] > chainLength)
{
chainLength = cache[i];
startingNumber = i;
}
}
//-----------------------------------------------------------------------------------------------
duration = ((clock() - startTime)/(double)CLOCKS_PER_SEC);
cout << "Starting Number is: " << startingNumber << " with a length of: " << chainLength << endl;
cout << "Duration = " << duration << endl;
//-----------------------------------------------------------------------------------------------
getchar();
return 0;
}
所以我的错误发生在第54行,并说我没有权限访问这个内存。在C#中相同的代码工作得很好。为什么我不能在C++中使用这段代码?
在你for
循环,你这样做:
for (int i = 2; i <= 1000000; i++)
{
n = i;
chain = 0;
while (n != 1 && n >= i)
{
chain++;
if ((n % 2) == 0)
{
n = n/2;
}
else
{
n = n * 3 + 1;
}
}
//Store the chain length in cache
cache[i] = chain + cache[n];
//-------------------------------
if (cache[i] > chainLength)
{
chainLength = cache[i];
startingNumber = i;
}
}
在某些时候while (n != 1 && n >= i)
最有可能与n
大于1000000
结束。然后你会访问cache
(当你做cache[n]
)出界(它是[0:1000000]
)。
在while
循环之前加std::cout << "i is " << i << std::endl;
。之后添加 std::cout << "n is " << n << std::endl;
。运行程序,你会得到(几秒钟后):
...
i is 113381
n is 85036
i is 113382
n is 56691
i is 113383
n is -1812855948
Erreur de segmentation (core dumped)
你在这里。现在,您可以使用调试器,识别错误,修复错误(最有可能重做您的循环),并使其工作! ;-)
提示:由于n
变为负值,可能达到了int
的最大值...然后只需使用类型(如long long int
或uint64_t)。然后,你很可能不会有任何溢出(除非你让number
秽物)。
C#不会像C++那样管理内存。如果在这里访问数组超出范围(或者,如上所述,您刚刚获得幸运),则可能不会出现错误。我不熟悉C#。访问数组必须总是被避免,它可能有不确定的行为(可能导致或不能导致崩溃)。
我没有自己运行它,但我可以100%确定在循环退出后,n将为== 1或
我认为“ n!= 1“只会结束,如果它是1 ...我会如何解决这个问题?我似乎无法找到修复:/ – sLowDowN
@sLowDowN - 或..如果'n'得到否定的 - 请参阅我的文章:) –
运行和调试程序后:
//Store the chain length in cache
cache[i] = chain + cache[n];
n
似乎是0x93f20374
(在i
是113383
),这是负-1812855948
,或将利好2482111348
- 但溢出成为-1812855948
。
while (n != 1 && n >= i)
环路负n
结束,导致cache[n]
崩溃。
n如何得到负面?因为n只能被2除或乘以3 +1 ......这应该是一个非常简单的解决方案,但是我看不到它:D – sLowDowN
@sLowDowN - 因为它溢出了'n'是一个带符号的int,并且到+ 2482111348(unsignedded),用int替换为-1812855948。 –
像jpo38说:
提示:当n为负,也许它达到INT的最大值...使用调试器来验证,只需做,while循环之前:
这是我的问题,然后我将“int n”改为“long long n”,因为“long n”仍然很小,现在它给了我正确的答案。谢谢大家:)这么简单,但有时它是你看不到的小事。
该死的......我提到了我的帖子中的溢出,但为什么我没有得到更多的声誉! :-( – jpo38
这让我想到:在数学上证明当你使用64位整数时n不会溢出? –
Pastebin:糟糕 - 在SO上发布代码:很好。发布所有代码:错误 - 发布与问题相关的代码:很好 –
*在c#中的相同代码工作得很好。* - ** C#不是C++ ** – PaulMcKenzie
关闭一个错误。数组的索引从零开始,而不是从1开始。如果它在C#中起作用,那么您很幸运 - 即使它看起来适用于您选择的测试用例,C#中的代码也会有缺陷。 – Peter