2013-08-30 57 views
0
#include <iostream> 
#include <cmath> 

using namespace std; 

unsigned long long modExp(unsigned long long b, unsigned long long e, unsigned long long m) 
{ 
    unsigned long long remainder; 
    unsigned long long x = 1; 

    while (e != 0) 
    { 
     remainder = e % 2; 
     e= e/2; 

     // These lines 
     if(remainder==1) 
      x=(unsigned long long)fmodl(((long double)x*(long double)b),(long double)m); 
     b=(unsigned long long)fmodl(((long double)b*(long double)b),(long double)m); 
    } 
    return x; 
} 

int main() 
{ 
    unsigned long long lastTen = 0,netSum=0; 
    unsigned long long sec(unsigned long long,unsigned long long); 

    for(int i=1;i<1001;i++) 
    { 
     lastTen = modExp(i,i,10000000000); 
     netSum += lastTen; 
     netSum %= 10000000000; 
     cout << lastTen << endl ; 
    } 

    cout << netSum%10000000000 << endl; 
    cout << sizeof(long double) << endl; 
    return 0; 
} 

這是我的程序來計算系列總和的最後十位數。它使用算術指數技術來計算最後10位數。它適用於10^9。但是當我去10^10時它崩潰了。fmodl - 雙倍模數

因此,爲了使用更高大小的數據類型,我已經將數倍數轉換爲長倍數並將它們相乘(這將再次產生長倍數),所以如果我們對這個數取模數,我們將正確地得到答案。但是我沒有再次得到正確的答案,它導致了同樣的錯誤答案。

我認爲做出這樣的事情是這樣的

  • 一個unsigned long長爲8個字節,因爲我跳模我會得到大量的這樣乘以2,十位數字的10位數字會不符合無符號long long,因此它將在無符號long long中循環
  • 因此,對於上述點,我將unsigned long long轉換爲long double(即12個字節),並且由於它具有較大的空間,所以它足夠大以適合20個十位數字的兩個十位數字的產品

任何人都可以說這是什麼邏輯的缺陷?

+0

請你能正確地縮進你的'modExp'函數(就像'main'一樣)嗎?另外,'main'中的'sec'函數聲明是什麼? –

+0

雅我編輯了代碼。 –

回答

2

常見的long double實現不能完全代表所有20位十進制數字。

long double的特徵並不完全由C++標準決定,而且您也沒有說明您使用的是什麼實現。

long double的一個常見實現使用64位有效位。雖然它可能以十二個字節存儲,但它只使用十個字符,其中十六個用於符號和指數,剩餘64個用於有效位(包括明確的前導位)。

一個64位的有效可表示沒有錯誤的整數高達2 ,大約是1.845•10 。因此,它不能完全表示所有的20位數字。

+0

感謝您的回答!有沒有其他辦法可以解決這個問題? –