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

Ruby中浮点的一致舍入

  •  2
  • bryantsai  · 技术社区  · 15 年前

    我理解由于浮点数的不精确表示,以下代码“感觉”不一致。

    "%.1f" % 1.14 # => 1.1
    "%.1f" % 1.15 # => 1.1
    "%.1f" % 1.16 # => 1.2
    "%.0f" % 1.4 # => 1
    "%.0f" % 1.5 # => 2
    "%.0f" % 1.6 # => 2
    

    但是,是否有一种简单的方法可以将一致的浮点四舍五入5?一种方法可能是显式地执行字符串操作。有没有更简单的方法或现存的图书馆?

    4 回复  |  直到 12 年前
        1
  •  5
  •   Tobias Cohen    15 年前

    如果需要十进制精度,请使用 BigDecimal 而不是浮动。

    编辑 :在将数字传递给 % 否则,它将在舍入前转换为普通浮点。

    "%.1f" % BigDecimal('1.15').round(1) => "1.2"
    "%.0f" % BigDecimal('1.5').round(0) => "2"
    
        2
  •  2
  •   Community CDub    8 年前

    只需添加一个小的扰动,以确保浮点值低于0.5的值刚好结束。

    例如,

    x = 1.15
    "%.1f" % (1.000001*x)  # include correction for imprecise floating-point.
    

    这将足以处理格式问题,但不太可能导致相关错误。

    还有:我先前问题的一个明显的后续问题 here 很好,但为了完整起见。

        3
  •  1
  •   alony    12 年前

    函数 roundthis() 在本例中,演示了如何以可控、一致的方式对数字取整。注意小的软糖值。试着运行这个不带软糖的例子来看看会发生什么。

    def roundthis(x, m)
        return (x/m+0.50001).floor*m
    end
    
    for x in [1.14, 1.15, 1.16]
        print "#{x}   #{roundthis(x, 0.1)}  \n"
    end
    
    for x in [1.4, 1.5, 1.6]
        print "#{x}   #{roundthis(x, 1.0)}  \n"
    end
    

    将其放入名为roundtest.rb的文件中并执行打印。

    bash> ruby roundtest.rb
    1.14   1.1  
    1.15   1.2  
    1.16   1.2  
    1.4   1.0  
    1.5   2.0  
    1.6   2.0  
    

    请注意,四舍五入到最接近的2、15、0.005或其他值是很容易的。

        4
  •  0
  •   Alex Reisner    15 年前

    乘以100,然后四舍五入,再除以100:

    (1.15 * 100).round / 100.0 # => 1.15
    

    它并不完全优雅,但它避免使用字符串。