2013-08-03 157 views
0

有沒有人對haskell中的這個奇怪舍入有一個解釋(GHCi,版本7.2.1)。一切似乎罰款,除非我乘以100四捨五入 - 「100」有什麼特別之處?

*Main> 1.1 
1.1 

*Main> 1.1 *10 
11.0 

*Main> 1.1 *100 
110.00000000000001 

*Main> 1.1 *1000 
1100.0 

*Main> 1.1 *10000 
11000.0 

編輯:什麼是puzzeling我是舍入誤差僅顯示有100

編輯乘以時(2):我收到的意見,讓我認識到,這與haskell完全無關,而是浮點數的一個普遍問題。許多問題已經被問及(關於浮點數奇怪的問題),其中未解決的問題典型地將浮點數與實數混淆。

Perl,python,javascript和C都報告1.1 * 100.0 = 110.00000000000001。這裏是C做什麼

double  10.0 * 1.1 = 11.000000000000000000000000 
double 100.0 * 1.1 = 110.000000000000014210854715 
double   110.0 = 110.000000000000000000000000 
double 1000.0 * 1.1 = 1100.000000000000000000000000 

的問題(即使是110.0精確的表示)仍然懸而未決「爲什麼會發生這種只能用100乘以時發生」,但我想沒有一個簡單的答案,其他比完全步進浮點乘法(感謝Dax Fohl強調10在二進制中沒有特別之處)

+3

這個問題被問到[over](http://stackoverflow.com/questions/588004/is-javascripts-floating-point-math-broken)和[over](http://stackoverflow.com/questions/ 7185512/why-0-10-2-0-3-5-5511151231258e-17-in-php)和[over](http://stackoverflow.com/questions/6027937/javascript-float-subtract)。 – 2013-08-03 10:15:14

+3

我認爲馬丁是問爲什麼發生在100但不是1000或10000.我最初也覺得這很奇怪。但是(可能)原因是,乘10的乘方不僅僅是數字的移位;它通過一些二進制乘法器,最終得到它給你的尾數和指數。既然10在二進制文件中沒有什麼特別的地方,那麼你可以在第一眼看到奇怪的東西,就像這樣。 –

+0

[每個計算機科學家應該知道的關於浮點運算的知識](http://perso.ens-lyon.fr/jean-michel.muller/goldberg.pdf) – rampion

回答

2

的問題(即使是110.0可精確表述)「爲什麼這只是發生與100乘以時」仍懸而未決,但我想沒有一個簡單的答案,比其他通過浮點乘法

好充分加強,我想可能有東西而不去寫二進制乘法,假設IEEE 754算術和(默認)的長度可以說舍入到最近的舍入模式。

1.1d是實數1.1的一半ULP。當你乘以10,100,1000和幾個十的乘方時,你乘以一個數N可以精確地表示爲一個雙精度乘以真實乘法1.1 * N的結果可以精確表示的附加屬性作爲一個雙重的。這使得1.1 * N很適合浮點乘法的結果,我們將寫入RN(N * 1.1d)。但是,乘法不會自動舍入爲1.1 * N:

RN(N * 1.1d) = N * 1.1d + E1 with |E1| <= 0.5 * ULP(N*1.1d) 

      = N * (1.1 + E2) + E1 with |E2| <= 0.5 * ULP(1.1) 

      = N * 1.1 + (N * E2 + E1) 

現在的問題是| N * E2 + E1 |與ULP(N * 1.1d)相比,因爲我們假設N * 1.1恰好是一個浮點數,所以如果乘法結果(也是一個浮點數)在N * 1.1的1 ULP範圍內,它必須是N * 1.1。


總之,這與其說是有什麼特殊的約100 ...這是什麼特別之處真正1.1D * 100,其中1)接近二的冪,同時在其下方和2)具有將真實1.1轉換爲雙精度時出現與誤差相同符號的錯誤。

每次都是真正的N * 1。1d相對接近於2的最近次冪比1.1更接近於1,N的1.1d的浮點乘法結果必須恰好爲N * 1.1(我認爲)。這種情況的一個例子是剛好在1024以上的N = 1000,N * 1.1d〜1100.

當真實N * 1.1d相對接近2的直接上乘冪時,比1.1更接近2,是一個浮點數,表示N * 1.1d比N * 1.1好。但是,如果誤差E1和E2相互補償(即有相反的符號),則不應發生這種情況。

3

數字1.1不能用有限形式表示爲二進制。它看起來像1.00011001100110011 ...

簡單的floating-point arithmetic「舍入誤差」在數學上是不可避免的。如果您想要精確度,請使用十進制數字類型。

http://support.microsoft.com/kb/42980

+0

強制鏈接:http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html – jozefg

+3

我明白浮動不是實數。我的問題是,我不明白,爲什麼錯誤只顯示與100相乘時,而不是與10或1000相乘。 –

+1

它看起來像是一個簡單的增加或減少0的事情,但在二進制小數中是由浮點指針編號表示,它並不是那麼簡單。這就是爲什麼你看到你的行爲的本質。其他人鏈接了一篇關於comp sci應該知道的浮點數的偉大文章,我強烈推薦它。 –