2016-01-07 144 views
-2
#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++中使用這段代碼?

+5

Pastebin:糟糕 - 在SO上發佈代碼:很好。發佈所有代碼:錯誤 - 發佈與問題相關的代碼:很好 –

+2

*在c#中的相同代碼工作得很好。* - ** C#不是C++ ** – PaulMcKenzie

+1

關閉一個錯誤。數組的索引從零開始,而不是從1開始。如果它在C#中起作用,那麼您很幸運 - 即使它看起來適用於您選擇的測試用例,C#中的代碼也會有缺陷。 – Peter

回答

0

在你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#。訪問數組必須總是被避免,它可能有不確定的行爲(可能導致或不能導致崩潰)。

+0

我沒有自己運行它,但我可以100%確定在循環退出後,n將爲== 1或<1000000. –

+0

我認爲「 n!= 1「只會結束,如果它是1 ...我會如何解決這個問題?我似乎無法找到修復:/ – sLowDowN

+0

@sLowDowN - 或..如果'n'得到否定的 - 請參閱我的文章:) –

1

運行和調試程序後:

//Store the chain length in cache 
    cache[i] = chain + cache[n]; 

n似乎是0x93f20374(在i113383),這是負-1812855948,或將利好2482111348 - 但溢出成爲-1812855948

while (n != 1 && n >= i) 

環路負n結束,導致cache[n]崩潰。

+0

n如何得到負面?因爲n只能被2除或乘以3 +1 ......這應該是一個非常簡單的解決方案,但是我看不到它:D – sLowDowN

+0

@sLowDowN - 因爲它溢出了'n'是一個帶符號的int,並且到+ 2482111348(unsignedded),用int替換爲-1812855948。 –

1

像jpo38說:

提示:當n爲負,也許它達到INT的最大值...使用調試器來驗證,只需做,while循環之前:

這是我的問題,然後我將「int n」改爲「long long n」,因爲「long n」仍然很小,現在它給了我正確的答案。謝謝大家:)這麼簡單,但有時它是你看不到的小事。

+0

該死的......我提到了我的帖子中的溢出,但爲什麼我沒有得到更多的聲譽! :-( – jpo38

+0

這讓我想到:在數學上證明當你使用64位整數時n不會溢出? –

相關問題