如何将浮点数舍入到Ruby中指定数量的有效数字?

Ale*_*huk 8 ruby floating-point significant-digits

在Ruby中使用等效的R的signif函数会很好.

例如:

>> (11.11).signif(1)
10
>> (22.22).signif(2)
22
>> (3.333).signif(2)
3.3
>> (4.4).signif(3)
4.4 # It's usually 4.40 but that's OK. R does not print the trailing 0's
    # because it returns the float data type. For Ruby we want the same.
>> (5.55).signif(2)
5.6
Run Code Online (Sandbox Code Playgroud)

Vic*_*gin 13

可能有更好的方法,但这似乎工作正常:

class Float
  def signif(signs)
    Float("%.#{signs}g" % self)
  end
end

(1.123).signif(2)                    # => 1.1
(11.23).signif(2)                    # => 11.0
(11.23).signif(1)                    # => 10.0
Run Code Online (Sandbox Code Playgroud)


小智 5

这是一个不使用字符串或其他库的实现。

class Float
  def signif(digits)
    return 0 if self.zero?
    self.round(-(Math.log10(self).ceil - digits))
  end
end
Run Code Online (Sandbox Code Playgroud)


mu *_*ort 3

我在 Float 中没有看到类似的东西。Float 主要是本机类型的包装器double,考虑到常见的二进制/十进制问题,我对 Float 不允许操作有效数字并不感到惊讶。

然而,标准库中的BigDecimal确实理解有效数字,但同样,我没有看到任何允许您直接更改 BigDecimal 中的有效数字的内容:您可以要求它,但不能更改它。mult但是,您可以通过使用or方法的无操作版本来解决这个问题add

require 'bigdecimal'
a = BigDecimal.new('11.2384')
a.mult(1, 2) # the result is 0.11E2   (i.e. 11)
a.add(0, 4)  # the result is 0.1124E2 (i.e. 11.24)
Run Code Online (Sandbox Code Playgroud)

这些方法的第二个参数:

如果指定且小于结果的有效位数,则结果将根据 舍入到该位数BigDecimal.mode

使用 BigDecimal 会比较慢,但如果您需要细粒度控制或需要避免常见的浮点问题,它可能是您唯一的选择。