Ruby 为什么是1.001+;0.001不等于1.002?

Ruby 为什么是1.001+;0.001不等于1.002?,ruby,math,floating-point,Ruby,Math,Floating Point,我有一些代码: num1 = 1.001 num2 = 0.001 sum = num1 + num2 puts sum 我期望1.002000但我得到1.001999999998。为什么会出现这种情况?这是分数值二进制表示的一个常见的基本问题,不是特定于Ruby的 由于二进制值的实现方式,在“普通”十进制数学的预期结果和实际结果之间有时会存在明显的差异。也不例外——因为它基于行业标准的双精度(IEEE 754)格式,所以它在内部将非整数表示为二进制值,因此其近似值为十进制值 如果您需要在R

我有一些代码:

num1 = 1.001
num2 = 0.001
sum  = num1 + num2
puts sum

我期望
1.002000
但我得到
1.001999999998
。为什么会出现这种情况?

这是分数值二进制表示的一个常见的基本问题,不是特定于Ruby的

由于二进制值的实现方式,在“普通”十进制数学的预期结果和实际结果之间有时会存在明显的差异。也不例外——因为它基于行业标准的双精度(IEEE 754)格式,所以它在内部将非整数表示为二进制值,因此其近似值为十进制值

如果您需要在Ruby中做十进制计算,考虑使用<代码> BigDecimal < /C> >():


在一个完美的世界里,是的,你期望1.002000,但是你有一个错误,因为在浮点算术运算中舍入,你可以在网络机器上检查epsilon或者仅仅是浮点。 例如,您可以这样计算相对误差,ruby语言的误差机器是1e-15

f = 0.0
100.times { f += 0.1 }
p f                            #=> 9.99999999999998       # should be 10.0 in the ideal world.
p 10-f                         #=> 1.9539925233402755e-14 # the floating-point error.

你从num2中得到了什么?这是二进制算术的问题,而不是语言的问题。不能用二进制表示0.1,正如不能用十进制表示1/3一样。对于金钱来说,任何小数点都是不好的建议。最好推荐一个不依赖于浮点数(大或小)的真正类。@duffymo严格地说,是的,但出于OP的目的,最接近的原因是Ruby在默认情况下表示一个类似于
1.001
的值作为class:Float的实例(“使用本机体系结构的双精度浮点表示的不精确实数”,根据文档)。我提到了大多数语言中的情况,这是对OP显然认为这是一个Ruby特定问题的直接回应。不过,这一点值得注意。它不是Ruby,而是二进制数。您使用IEEE 754标准以有限宽度表示浮点数。所有语言都是如此,而不仅仅是Ruby.@duffymo,我明白,我是在回应OP(显然没有经验)将问题描述为Ruby问题的。(“为什么Ruby中会出现这种情况?”“大多数语言中都会出现这种情况,包括Ruby,原因如下。”)IEEE 754表示法并非所有语言都必须具备的功能,例如,某些语言默认情况下可能会使用类似dec64的功能,但这一点并不完全正确。我已经对我的措辞进行了编辑,希望它能够非常清楚。尽管问题在许多语言中都会出现,但这个答案不仅提供了解释,而且提供了一个ruby避免问题的解决方案。
f = 0.0
100.times { f += 0.1 }
p f                            #=> 9.99999999999998       # should be 10.0 in the ideal world.
p 10-f                         #=> 1.9539925233402755e-14 # the floating-point error.