在Ruby中,如何将浮点舍入到指定的有效位数?
在Ruby中有一个等价的函数会很好 例如:在Ruby中,如何将浮点舍入到指定的有效位数?,ruby,floating-point,significant-digits,Ruby,Floating Point,Significant Digits,在Ruby中有一个等价的函数会很好 例如: >> (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
>> (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
我在浮子上没看到类似的东西。Float主要是本机
double
类型的包装器,考虑到常见的二进制/十进制问题,Float不允许您操作有效数字并不奇怪
然而,在标准库中,确实可以理解有效数字,但我没有看到任何允许您直接更改BigDecimal中的有效数字的内容:您可以请求它,但不能更改它。但是,您可以通过使用无操作版本的mult
或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)
这些方法的第二个参数:
如果已指定且小于结果的有效位数,则根据BigDecimal.mode
将结果四舍五入到该位数
使用BigDecimal会比较慢,但是如果您需要细粒度的控制,或者需要避免常见的浮点问题,那么它可能是您唯一的选择。您可能正在寻找Ruby的 然后你可以写:
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(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
如果要打印尾随零,请使用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 >
之前的一些回答和评论都提到了这个解决方案,但这对我来说是有效的:
# 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
@Blou91的答案几乎是正确的,但它返回的是字符串,而不是浮点。下面这个对我很有用:
(sprintf "%.2f", 1.23456).to_f
所以作为一种功能
def round(val, sig_figs)
(sprintf "%.#{sig_figs}f", val).to_f
end
这是一个不使用字符串或其他库的实现
class Float
def signif(digits)
return 0 if self.zero?
self.round(-(Math.log10(self).ceil - digits))
end
end
这个问题适合你吗?太棒了!它是printf(又称sprintf,又称sprintf%)的“g”说明符,然后转换为float!明亮的这个实现应该内置到Ruby中。有人想提交补丁吗?等等。细微差别:(5.55).signif(2)#应该是=>5.6,但给出5.5I对于ruby 1.9()的良好拉取请求来说,已经超过了一半!但是需要注意(5.55)。signif(2)#=>5.6我正在考虑将R中的代码采用/集成到Ruby的numeric中。c接受第二个参数,该参数限制数字的有效位数。@jwadsack:但这仅在创建新的BigDecimal时有效,无法更改现有BigDecimal的
数字值。我想这就是我所说的“我看不到任何允许你直接改变BigDecimal中的有效数字”的意思。这四舍五入到具体的小数位数,但我们想要的是四舍五入到具体的有效数字位数。