2017-11-25 32 views
-3

我在C語言初學者,我旨在對項目歐拉回答問題138。爲您的網站的好處是鏈接:https://projecteuler.net/problem=138項目歐拉138 - C代碼未存儲號碼正確

那麼下面顯示的是我的代碼

#include <stdio.h> 
#include <math.h> 

unsigned long long L(unsigned long long b); 

int main() { 

    unsigned long long sigma = 0; 
    int n = 0; 
    int b = 16; 
    while (n < 12) { 

     unsigned long long l = L(b); 
     if (l != 0) { 
      n++; 
      sigma += l; 
     } 
     b++; 
    } 
    printf("%lld\n", sigma); 
} 

unsigned long long L(unsigned long long b) { 

    unsigned long long L = 0; 
    unsigned long long X1 = 5 * (b * b) + (8 * b) + 4; 
    unsigned long long x1 = sqrt(X1); 
    unsigned long long X2 = 5 * (b * b) - (8 * b) + 4; 
    unsigned long long x2 = sqrt(X2); 

    if (X1 == x1 * x1 && x1 % 2 == 0) { 
     L += x1/2; 
    } 
    if (X2 == x2 * x2 && x2 % 2 == 0) { 
     L += x2/2; 
    } 
    return L; 
} 

當問題問的前十二,我設置了循環終止當n = 12,但是這個代碼沒有給出正確的答案。我最初雖然有一個邏輯錯誤,但當我設置循環終止一個n = 2時,程序給出了正確的答案。我懷疑它與存儲在變量中的數字有關,但當然我可能是錯的。

誰能一些線索這是我敢肯定的邏輯是正確的?

+5

一個可能的問題是,['sqrt'](http://en.cppreference.com/w/c/numeric/math/sqrt)是一個浮點功能,所以結果可能會被截斷。並且請儘量避免與'X1'和'x1'這樣密切相關的變量,它們很難區分。 L函數中的函數'L'和局部變量'L' *一樣。 –

+0

那麼有沒有解決這個問題的方法? –

+0

@JohnDoe將所有整數類型更改爲浮點類型。 –

回答

0
  1. b傳遞給L最大的價值將至少2168393136。然而,如果int爲32位,這溢出的int,2147483647的最大值。 b應該作爲unsigned int(或任何更寬的整數類型)。

  2. 功能L計算5*b*b + 8*b + 4。由於最大b是略超過2 ,這個表達式的數學值稍微超過2 。除非unsigned long long寬度大於64位,這超過了unsigned long long最大值,條件是不期望的值計算出的結果。

  3. L適用於sqrtX1(和X2)。這將值轉換爲double,通常有53位的精度。由於該值有65位,因此丟失了12位。幸運的是,平方根的導數在這個數值上是非常小的,所以輸入的大變化會產生輸出的小變化。所以sqrt結果應該是附近的精確的數學結果,它應該是調整的結果找到最接近精確的數學平方根的整數可行的,然後可以用來測試是否X1是一個確切的平方。或者,可以寫一個整數平方根例程。

  4. 一旦上述問題得到解決,程序可能會比以前繼續更進一步,這將導致使用更大的值b。持續評估可能是必要的,以確保類型足夠寬和足夠精確的工作。 (我嘗試了雜牌擴展代碼能夠支持的領域。這是目前用b超逾16十億在運行。我可以有一個錯誤,但我認爲你應該相當大的數量來準備。)

總之,C和普通實現的本地類型不支持直接進行這種算術。有必要編寫特殊的代碼來處理大數字或解決它們。

由於歐拉項目問題,像這樣的一點是要推的界限內置的算術,那就是答案應該停止,學生應該從那裏繼續思考。