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
在 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