Ruby 的 BigDecimal class 中的浮点错误?

floating point error in Ruby's BigDecimal class?

在 ruby 中避免浮点错误的通用建议是使用 BigDecimal。我一定是忽略了一些东西,因为我想我发现了一个 BigDecimal 数学返回错误而 Float 没有的情况:

使用浮点数给出正确答案 2.75:

> 50.0 * 0.6 / 360.0 * 33
=> 2.75

使用 BigDecimal 得出错误答案 2.74999999:

> BigDecimal("50") * BigDecimal("0.6") / BigDecimal("360") * BigDecimal("33")
=> #<BigDecimal:7efe74824c80,'0.2749999999 999999989E1',27(36)>

谁能告诉我我在这里遗漏了什么?

让我们简化您的示例,改用这个示例:

BigDecimal(1) / BigDecimal(3) * BigDecimal(3)
# => #<BigDecimal:19289d8,'0.9999999999 99999999E0',18(36)>

它是如何到达那里的?

BigDecimal(1) / BigDecimal(3)
# => #<BigDecimal:1921a70,'0.3333333333 33333333E0',18(36)>

BigDecimal不提供有理数,所以1除以3得到0,后面跟着很多3。很多,但不是无限多。然后将其乘以 3,您将得到 0,后跟同样多的 9。

我相信您误读了 BigDecimal 的广告(尽管我不确定在任何地方都宣传它是解决浮点错误的方法)。它只是提供任意精度。它仍然是一个浮点数。如果你在除数时真的想要精确的数字,你可以看看 Rational class:

(Rational(50) * Rational(0.6) / Rational(360) * Rational(33)).to_f
# => 2.75