2012-08-31 82 views
2

我有一段代碼,上面寫着:添加長雙打給出了C中的錯誤的答案++

std::cerr << val1 << " " << val2 << std::endl; 
val1 = val1 + val2; 
std::cerr << val1 << std::endl; 

兩個VAL1和val2長一倍。

的問題來自於一個事實,即這樣做的結果是:

-5.000000000000722771452063564190e-01 2.710505431213761085018632002175e-20 
-5.000000000000722771452063564190e-01 

這是沒有意義的。看來val2沒有被添加到val1中,但是,在val1的小數部分顯然有足夠的信息可以將val2添加到它。

我很難過,任何人有任何想法?

我使用GCC 4.2我相信。 G ++是否使用IEEE四倍精度格式?或者別的東西(比如80位擴展精度,這可以解釋這個問題(儘管爲什麼會出現超過18個小數位?)

+1

和最新的'的實際價值val1'&'val2' ?? – perilbrain

+0

Obligatory Goldberg鏈接:http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html –

+0

這是什麼架構和操作系統運行? –

回答

4

嗯,我應該猜到了...它看起來像G + +上的long double以四位精度格式存儲,但是使用80位擴展精度格式計算,所以它會給出很多數字,但只有一些數字被計算出來

5

如果你的val1和val2打印正確,那麼輸出是正確的: -

-5.000000000000722771452063564190e-01 = -5.000000000000722771452063564190 X e^(-1) //or 10^(-1) 

其中^ denotes to the power of

2.710505431213761085018632002175e-20 = -5.000000000000722771452063564190 X e^(-20) //or 10^(-20) 

..

Since val1 >> val2 
=> lim (val2/val1 -> 0) (lim is mathematical limit) .... eq (A) 

Consider y=val1+val2 
=> y= ((val1+val2)/val1)*val1 (rationalizing) 
=> y= {(val1/val1)+(val2/val1)} * val1 
=> y= {1+val2/val1}*val1 
=> y= {1+0}*val1 .........................................From eq (A) 
=> y= val1 

這就是爲什麼輸出是-5.000000000000722771452063564190e-01(因爲通過添加所產生的差落在出表示由二進制長雙精度格式的範圍內的)

+0

我認爲'e-01'實際上意味着'* 10 ^(-01)'。 –

+0

@MatthieuM:它的確如此。對於匿名ymous另外,如果您注意到,四倍精度浮點中可用的精度位數是〜35個十進制數字(遠大於兩個數字之間的19個數量級差異),這意味着它們應該被添加。但是,正如我在我的回答中所提到的,在G ++中,long double是用擴展的精度數字(具有大約19位精度)計算的。此外,你應該檢查你的數學......這沒有多大意義(你除以零,在其他錯誤)。 –

相關問題