为什么这会可变地变为负值?

Why is this variably turning negative?

所以我的错误提示我没有访问此内存的权限。 这是它的代码,我正在尝试让 collaz 系列工作。 但是我的 n 正在变负,尽管它不应该。

const int number = 1000000;

//Chain Vars-------------------
int chainLength = 0;
int startingNumber = 0;
int chain = 0;
int n = 0;
//----------------------------

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;
        }
    }
}

在你的 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 bugger)。

C# 不像 C++ 那样管理内存。如果在此处越界访问数组,您可能不会出错(或者,如上文所述,您只是走运)。我不熟悉 C#。必须始终避免访问数组,因为它可能具有未确定的行为(可能会或不会导致崩溃)。

运行并调试程序后:

    //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] 崩溃。

就像 jpo38 说的:

提示:当 n 变为负数时,可能它达到了 int 的最大值...使用调试器来验证这一点,只需在 while 循环之前执行:

那是我的问题,然后我将 "int n" 更改为 "long long n" 因为 "long n" 仍然很小,现在它给了我正确的答案。谢谢大家 :) 如此简单,但有时是您看不到的小事情。