Ruby round 向上或向下浮动到指定的十进制有效数字

Ruby round Float up or down to specific decimal significant figure

我正在使用 Ruby 2.3.1,这就是我希望能够做到的:

1.33333333.ceil(2) -> 1.34
1.33333333.floor(3) -> 1.333

Float#round 方法允许我 round,但我需要能够指定是否要向上或向下舍入,类似于 [=13] =] 和 #floor 方法,但带有一个参数来指定保留多少位小数。

Ruby 2.4+ 中,Float#floatFloat#ceil 方法采用 ndigits 参数:

1.33333333.ceil(2) -> 1.34
1.33333333.floor(3) -> 1.333

但是,使用这些 STD 库方法检查此行为:

# In Ruby 2.4.2:
0.07.ceil(2) -> 0.08
1.1.ceil(2) -> 1.11

我认为不合适。

对于较旧的 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

现在详细了解为什么以下内容不正确

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

我不会详细说明正在发生的事情(你可以找到 here or here), 但浮点运算可能会很混乱并且会出现舍入错误。