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

在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 

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

 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 

之前的一些答案和评论已经提到了这个解决方案,但这对我有用:

 # takes in a float value and returns another float value rounded to # given significant figures. def round_to_sig_figs(val, sig_figs) BigDecimal.new(val, sig_figs).to_f end 

我没有在Float中看到类似的东西。 Float主要是原生double类型的包装器,并且给出了通常的二进制/小数问题,Float不允许你操纵有效数字我并不感到惊讶。

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

 require 'bigdecimal' a = BigDecimal.new('11.2384') a.mult(1, 2) # the result is 0.11E2 (ie 11) a.add(0, 4) # the result is 0.1124E2 (ie 11.24) 

这些方法的第二个参数:

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

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

你可能正在寻找Ruby的Decimal 。

然后你可以写:

 require 'decimal/shortcut' num = 1.23541764 D.context.precision = 2 num_with_2_significant_digits = +D(num.to_s) # => Decimal('1.2') num_with_2_significant_digits.to_f # => 1.2000000000000002 

或者,如果您更喜欢使用相同的语法,请将此函数添加为类Float,如下所示:

 class Float def signif num_digits require 'decimal/shortcut' D.context.precision = num_digits (+D(self.to_s)).to_f end end 

然后用法是相同的,即

  (1.23333).signif 3 # => 1.23 

要使用它,请安装gem

 gem install ruby-decimal 

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

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

@ Blou91的答案几乎就在那里,但它返回一个字符串,而不是浮点数。 以下内容对我有用:

 (sprintf "%.2f", 1.23456).to_f 

所以作为一个function,

 def round(val, sig_figs) (sprintf "%.#{sig_figs}f", val).to_f end 

如果要打印尾随零,请使用sprintf

 2.0.0-p353 :001 > sprintf "%.3f", 500 => "500.000" 2.0.0-p353 :002 > sprintf "%.4f", 500 => "500.0000" 2.0.0-p353 :003 >