【问题标题】:Ruby Float#round method behaves incorrectly with round(2)Ruby Float#round 方法在 round(2) 中的行为不正确
【发布时间】:2012-09-09 10:55:36
【问题描述】:

我了解到建议使用BigDecimal 而不是Float,但这不是一个错误,就是突出了Float 的深奥本质。看来Float#round(2)“1.015”、“1.025”和“1.035”有问题。

1.015.round(2)
 => 1.01    # => WRONG .. should be 1.02
1.025.round(2)
 => 1.02    # => WRONG .. should be 1.03
1.035.round(2)
 => 1.03    # => WRONG .. should be 1.04
1.045.round(2)
 => 1.05    # => CORRECT
1.016.round(2)
 => 1.02    # => CORRECT

round(3) 工作正常。

1.0015.round(3)
 => 1.002  # => CORRECT
1.235.round(2)
 => 1.24   # => CORRECT 

为了在 Rails 应用程序中修改这个,我这样做了:

config/initializers/float_mp.rb

require 'bigdecimal'

class Float
  def round(val=0)
     BigDecimal.new(self.to_s).round(val).to_f
  end
end

这似乎是一种奇怪且昂贵的解决方法。这可能是Float#round 中的错误吗?

【问题讨论】:

  • 不幸的是,这就是二进制浮点的工作方式。如果你想要这样严格的行为,你的“昂贵的话语权”就是这样做的。
  • 您正在寻找可预测的 binary 近似值,将 binary 近似值的 decimal 四舍五入到 decimal 中途案例。这就是疯狂!

标签: ruby floating-point floating-accuracy ruby-1.9.3


【解决方案1】:

AFAICS ruby​​ round() 工作正常。大概它只是 libm 中 round() 函数的一个包装器。

所以原因是你的浮点文字不能用二进制精确表示。例如。 “1.015”多打印几位小数给出“1.0149999999999999”;因此,当四舍五入到两位小数时,1.01 比 1.02 更接近真实值。对于您的其他示例,依此类推。

另外请记住,默认的 IEEE 754 舍入模式是“四舍五入,与偶数相等”,这与您在学校可能熟悉的“四舍五入,从零开始”不同.

【讨论】:

    猜你喜欢
    • 2019-01-14
    • 2013-03-22
    • 2015-09-21
    • 2010-11-07
    • 2014-04-08
    • 2021-03-06
    • 2019-08-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多