jsm*_*rtt 3 ruby floating-point rounding floor ceil
我正在使用 Ruby 2.3.1,这是我想要做的:
1.33333333.ceil(2) -> 1.34
1.33333333.floor(3) -> 1.333
Run Code Online (Sandbox Code Playgroud)
该Float#round方法允许我舍入,但我需要能够指定是向上还是向下舍入,类似于#ceil和#floor方法,但带有一个参数来指定要保留的小数位数。
在Ruby 2.4+ 中,Float#float&Float#ceil方法接受一个ndigits参数:
1.33333333.ceil(2) -> 1.34
1.33333333.floor(3) -> 1.333
Run Code Online (Sandbox Code Playgroud)
但是,请使用这些 STD lib 方法检查此行为:
# In Ruby 2.4.2:
0.07.ceil(2) -> 0.08
1.1.ceil(2) -> 1.11
Run Code Online (Sandbox Code Playgroud)
在我的书中不好。
对于较旧的 Ruby 版本,或者如果您想获得比 STB 库提供的更好的结果,则需要编写自己的方法。有一些不同的博客文章,稍后我将解释为什么它们不是始终正确的,但这里有一些方法每次都应该正确工作:
require 'bigdecimal'
class Float
def ceil2(exp = 0)
BigDecimal(self.to_s).ceil(exp).to_f
end
def floor2(exp = 0)
BigDecimal(self.to_s).floor(exp).to_f
end
end
Run Code Online (Sandbox Code Playgroud)
现在了解更多关于为什么以下不正确的信息:
def ceil_to(x)
(self * 10**x).ceil.to_f / 10**x
end
def floor_to(x)
(self * 10**x).floor.to_f / 10**x
end
# These methods also produce bad results for the examples shown above
0.07.ceil(2) -> 0.08
1.1.ceil(2) -> 1.11
Run Code Online (Sandbox Code Playgroud)
我不会详细介绍正在发生的事情(您可以在此处或此处找到 ),但浮点运算可能很混乱,并且确实会发生舍入错误。