Ruby Floatround方法与round(2)的行为不正确
我了解到建议使用BigDecimal而不是Float,但这一个要么是一个bug,要么突出了Float的深奥本质。看起来Floatround2在1.015、1.025和1.035上有问题Ruby Floatround方法与round(2)的行为不正确,ruby,floating-point,floating-accuracy,ruby-1.9.3,Ruby,Floating Point,Floating Accuracy,Ruby 1.9.3,我了解到建议使用BigDecimal而不是Float,但这一个要么是一个bug,要么突出了Float的深奥本质。看起来Floatround2在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 # =
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
第三轮很好
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
这似乎是一项奇怪而昂贵的工作。这可能是Floatround中的错误吗?因为ruby round工作正常。想必它只是libm中round函数的包装器 因此,原因是您的浮点文本不能用二进制精确表示。例如,如果1.015再加上几个小数,则表示1.01499999999;因此,当四舍五入到两位小数时,1.01比1.02更接近真值。其他例子也是如此
还请记住,默认的IEEE 754舍入模式是“舍入到最近值”,与“舍入到最近值”不同的是“舍入到最接近值”,与“零”不同的是,这是您在学校可能熟悉的。不幸的是,这是二进制浮点的工作方式。如果你想要如此严格的行为,你的昂贵的词周围是这样做的方式。你正在寻找可预测的二进制近似的结果十进制四舍五入的二进制近似到十进制的一半情况。那就是疯狂!