2010-10-29 211 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。这主要是运气。底线是,从来没有期望任何浮点算术的平等,只有“亲密度”。