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

时间:2018-04-04 16:56:45

标签: ruby floating-point rounding floor ceil

我正在使用Ruby 2.3.1,这是我想要的能够做到的事情:

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

Float#round方法允许我围绕,但我需要能够指定是否要向上舍入或向下舍入,类似于#ceil和{{ 1}}方法,但有一个参数来指定要保留的小数位数。

1 个答案:

答案 0 :(得分:1)

Ruby 2.4+Float#float& Float#ceil方法采用ndigits参数:

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

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

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

在我的书中不行。

对于较旧的Ruby版本,或者如果你想获得比STB lib更好的结果,你需要编写自己的方法。有一些不同的博客文章,我将解释为什么它们以后不一致正确,但这里有一些方法应该每次都能正常工作:

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

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