ruby 浮点迭代问题

ruby issue with float point iteration

当我运行代码

count = 0

while count < 1
  count += 0.1
  puts count
end

我希望

0.1 
0.2 
0.3 
. . . 

不过我一直在

0.1
0.2
0.30000000000000004
0.4
0.5
0.6
0.7
0.7999999999999999
0.8999999999999999
0.9999999999999999
1.0999999999999999

谁能帮忙解释一下?

浮点数不能精确表示所有的实数,浮点运算也不能精确表示真正的算术运算,这就导致了很多令人吃惊的情况。

我建议阅读:https://en.wikipedia.org/wiki/Floating_point#Accuracy_problems

您可能希望使用 BigDecimal 来避免此类问题。

这样想:

您的计算机只有 32 位或 64 位来表示数字。这意味着它只能表示有限数量的数字。

现在考虑 0 到 1 之间的所有十进制值。它们的数量是无限的。如果您的机器甚至不能表示 0 到 1 之间的所有数字,您怎么可能表示所有实数?

答案是您的机器需要近似十进制数。这就是您所看到的。

当然there are libraries that try to overcome these limitations并做到这一点,这样您仍然可以准确地表示十进制数。 BigDecimal 就是这样一种库:

require 'bigdecimal'

count = BigDecimal.new("0")
while count < 1
  count += 0.1
  puts count.to_s('F')
end

缺点是这些库的算术速度通常较慢,因为它们是 CPU 之上的软件层来进行这些计算。

这是浮点数在内存中表示的众多后果之一!

要解释到底发生了什么会很长,并且其他人之前已经做得更好,对您来说最好的办法是阅读其他地方的内容:

您还可以查看之前关于 SO 的问题:

  • What is a simple example of floating point/rounding error?
  • Ruby BigDecimal sanity check (floating point newb)