Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Ruby中,如何将浮点舍入到指定的有效位数?_Ruby_Floating Point_Significant Digits - Fatal编程技术网

在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

在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 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中的有效数字”的意思。这四舍五入到具体的小数位数,但我们想要的是四舍五入到具体的有效数字位数。