【问题标题】:ruby issue with float point iteration [duplicate]浮点迭代的红宝石问题[重复]
【发布时间】:2015-05-03 00:26:57
【问题描述】:

当我运行代码时

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

谁能帮忙解释一下?

【问题讨论】:

标签: ruby floating-point


【解决方案1】:

这样想:

您的计算机只有 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 之上的一个软件层来执行这些计算。

【讨论】:

  • 使用Rational 会更容易。
  • BigDecimal 是不是和Float 有同样的问题(只是导致问题稍后出现)?
  • 是的,我同意你的看法。它不能准确地表示所有值。但是,您可以设置所需的精度,然后放心地将其用于该精度级别内的特定计算 - 这就是它比使用简单的浮点值更有用的原因。
  • @sawa:总之,没有。
【解决方案2】:

浮点数不能精确地表示所有实数,浮点运算也不能精确地表示真正的算术运算,这会导致许多令人惊讶的情况。

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

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

【讨论】:

    【解决方案3】:

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

    要解释到底发生了什么会很长,而且其他人之前已经做得更好了,对你来说最好的事情是阅读其他地方去阅读它:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-18
      • 1970-01-01
      • 2013-01-18
      • 2016-03-23
      • 2011-05-23
      • 1970-01-01
      • 2011-07-15
      相关资源
      最近更新 更多