有人可以解释为什么乘以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