代码之家  ›  专栏  ›  技术社区  ›  jsmartt

红宝石四舍五入上浮或下浮至特定十进制有效数字

  •  4
  • jsmartt  · 技术社区  · 7 年前

    我使用的是Ruby 2.3.1 希望 能够做到:

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

    这个 Float#round 方法允许我 圆形的 ,但我需要能够指定是向上取整还是向下取整,类似于 #ceil #floor 方法,但有一个参数指定要保留的小数位数。

    1 回复  |  直到 7 年前
        1
  •  6
  •   jsmartt    7 年前

    在里面 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库更好的结果,则需要编写自己的方法。有一些不同的博客帖子,我稍后会解释为什么它们不总是正确的,但这里有一些每次都应该正确工作的方法:

    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 here ),但浮点运算可能会很混乱,并且会出现舍入错误。