ruby浮点错误

ruby浮点错误,ruby,floating-point,Ruby,Floating Point,有人能解释为什么这里乘以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 首先:您看到的是结果的字符串表示,而不是实际结果本身。如果确实要比较这两个结果,则应使用String%显式设置两个

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

首先:您看到的是结果的字符串表示,而不是实际结果本身。如果确实要比较这两个结果,则应使用
String%
显式设置两个结果的格式,并且两个结果的格式应相同


其次,二进制浮点数就是这样工作的。它们是不精确的,它们是有限的,它们是二进制的。这三种情况都意味着你会出现舍入错误,这通常看起来完全是随机的,除非你碰巧记住了IEEE754的全部内容,并且可以在睡眠中倒背如流。

没有一个浮点数正好等于
129.95
。所以你的语言使用了一个接近它的值。当该值乘以100时,结果接近12995,但恰好不等于12995。(它也不完全等于它用来代替
129.95
的原始值的100倍),因此您的解释器打印一个接近(但不等于)
129.95*100
值的十进制数,这表明它不完全是12995。结果
129.95*10
正好等于1299.5。这主要是运气


底线是,不要期望任何浮点运算都相等,只有“接近度”。

如果你用双精度二进制(限制为53个有效位)手工计算,你会看到发生了什么:

129.95=1.0000001111100x110 x 2^7

129.95*100=1.10010110000101111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111

这是56个有效位长,所以四舍五入到53位

1.10010110000101111111111111111111111111111111111111111111111111x113,等于

12994.999999999981810105964541435424169921875

现在129.95*10=1.01000110111111111111111111111111111111 x 2^10

这是54个有效位长,因此四舍五入到53位,即1.01000111 x 2^10=1299.5


现在1299.5*10=1.1001011000011 x 2^13=12995。

很可能是由于浮点数的二进制表示。我想你不能在基数2中写出129.95。强制性链接:有什么线索可以解释为什么这不会发生在我身上?我试图证明这一点,我在IRB中输入了上面的129.95*100,我意外地得到了正确的答案。这样做有效:printf(“%.50f”,129.95*100)