0

下面的代码输出 0.0。这是因为溢出吗?如何避免?如果不是,为什么?

p ((1..100000).map {rand}).reduce :*

我希望加快这段代码的速度:

p r.reduce(0) {|m, v| m + (Math.log10 v)}

并改用它:

p Math.log10 (r.reduce :*)

但显然这并不总是可能的......

4

3 回答 3

3

rand 产生的值都在 0.0 到 1.0 之间。这意味着每次乘法时,您的数字都会变小。因此,当您将它们乘以 1000 时,它可能与 0 无法区分。

在某些时候,ruby 会让你的数字变得如此之小以至于它是 0。例如:2.0e-1000 # => 0

于 2013-01-11T21:36:01.830 回答
1

每次乘法都会将您的数字减少约1/2 1,因此在其中约 50 次之后,您下降了1/2 50并且在 100000 之后(实际上,在约 700 之后)您已经下溢FP 格式本身,请参见此处。

于 2013-01-11T21:39:21.293 回答
0

Ruby 提供了BigDecimal实现精确浮点运算的类。

require 'bigdecimal'

n = 100

decimals = n.times.map { BigDecimal.new rand.to_s }
result = decimals.reduce :*

result.nonzero?.nil?  # returns nil if zero, self otherwise
# => false

result.precs  # [significant_digits, maximum_significant_digits]
# => [1575, 1764]

Math.log10 result
# => -46.8031931083014

但是,它比本机浮点数慢得多。随着n = 100_000decimals.reduce :*通话在我的电脑上持续了几分钟,然后我终于中断了它。

于 2013-01-11T22:10:10.733 回答