2010-10-29 214 views
9

有人可以解釋爲什麼乘以100在這裏給出一個不太準確的結果,但乘以10兩次給出更準確的結果?紅寶石浮點錯誤

± % sc 
Loading development environment (Rails 3.0.1) 
>> 129.95 * 100 
12994.999999999998 
>> 129.95*10 
1299.5 
>> 129.95*10*10 
12995.0 
+1

最可能是由於浮點數的二進制表示。我假設你不能在基數2中以驚人的速度寫出129.95。 – 2010-10-29 20:28:37

+10

必須鏈接:[每個計算機科學家應該知道的關於浮點算術](http://docs.sun.com/source/806-3568/ncg_goldberg.html) – 2010-10-29 21:00:34

+0

任何線索爲什麼這不會發生我?我試圖證明這一點,並且如上所述將129.95 * 100輸入IRB,並且我意外地得到了正確的答案。 – Joel 2013-11-12 04:57:43

回答

22

如果您在雙精度二進制,這是僅限於53顯著位手做計算,你會看到這是怎麼回事:

129.95 = 1.0000001111100110011001100110011001100110011001100110×2^7

129.95 * 100 = 1.1001011000010111111111111111111111111111111111111111011×2^13

這是56個比特顯著長,所以四捨五入至53位是

1.10010110000101111111111111111111111111111111111111 11×2^13,它等於

12994.999999999998181010596454143524169921875

現在129.95 * 10 = 1.01000100110111111111111111111111111111111111111111111×2^10

這是54顯著位長,所以四捨五入至53位是1.01000100111×2^10 = 1299.5

現在1299.5 * 10 = 1.1001011000011×2^13 = 12995.

3

首先:您正在查看結果的字符串表示形式,而不是實際結果本身。如果真的要想要比較兩個結果,則應該使用String#%明確地格式化兩個結果,並且應該以相同的方式格式化兩個結果。其次,這就是二進制浮點數的工作原理。它們不準確,它們是有限的,它們是二元的。所有這三個意味着你會得到四捨五入的錯誤,通常看起來完全是隨機的,除非你碰巧記住了整個IEEE754,並且可以在睡眠中向後背誦。

2

沒有浮點數完全等於129.95。所以你的語言使用一個接近它的值。當該值乘以100時,結果接近12995,但恰好不等於12995.(它也不完全等於它用來代替129.95的原始值的100倍)。因此,您的解釋器打印一個十進制數字,它接近(但不等於)129.95 * 100的值,並且顯示它不完全是12995.它也恰好是129.95 * 10的結果恰好等於1299.5。這主要是運氣。底線是,從來沒有期望任何浮點算術的平等,只有「親密度」。