有人可以解釋爲什麼乘以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
有人可以解釋爲什麼乘以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
如果您在雙精度二進制,這是僅限於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.
首先:您正在查看結果的字符串表示形式,而不是實際結果本身。如果真的要想要比較兩個結果,則應該使用String#%
明確地格式化兩個結果,並且應該以相同的方式格式化兩個結果。其次,這就是二進制浮點數的工作原理。它們不準確,它們是有限的,它們是二元的。所有這三個意味着你會得到四捨五入的錯誤,通常看起來完全是隨機的,除非你碰巧記住了整個IEEE754,並且可以在睡眠中向後背誦。
沒有浮點數完全等於129.95
。所以你的語言使用一個接近它的值。當該值乘以100時,結果接近12995,但恰好不等於12995.(它也不完全等於它用來代替129.95
的原始值的100倍)。因此,您的解釋器打印一個十進制數字,它接近(但不等於)129.95 * 100
的值,並且顯示它不完全是12995.它也恰好是129.95 * 10
的結果恰好等於1299.5。這主要是運氣。底線是,從來沒有期望任何浮點算術的平等,只有「親密度」。
最可能是由於浮點數的二進制表示。我假設你不能在基數2中以驚人的速度寫出129.95。 – 2010-10-29 20:28:37
必須鏈接:[每個計算機科學家應該知道的關於浮點算術](http://docs.sun.com/source/806-3568/ncg_goldberg.html) – 2010-10-29 21:00:34
任何線索爲什麼這不會發生我?我試圖證明這一點,並且如上所述將129.95 * 100輸入IRB,並且我意外地得到了正確的答案。 – Joel 2013-11-12 04:57:43