我了解到建议使用BigDecimal而不是Float,但这一个要么是一个bug,要么突出了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中的错误吗?

最佳答案

AFAICS the ruby round()工作正常不管怎样,可能只是libm中round()函数的包装器。
所以原因是浮点字面值不能用二进制来精确表示例如,如果“1.015”再多打印几位小数,则表示“1.0149999999999999999”;因此,当四舍五入到两位小数时,1.01比1.02更接近真实值其他例子也是如此。
还要记住,默认的IEEE 754舍入模式是“舍入到最接近的值,连到偶数”,这与“舍入到最接近的值,连到远离零的值”不同,这是你在学校可能熟悉的。

07-24 09:45
查看更多