下面的代码输出0.0。这是因为溢出?怎么避免呢?如果没有,为什么?
p ((1..100000).map {rand}).reduce :*
我希望加快这段代码:
p r.reduce(0) {|m, v| m + (Math.log10 v)}
并改为使用:
p Math.log10 (r.reduce :*)
但显然这并非总是可行......
答案 0 :(得分:3)
rand生成的值都在0.0到1.0之间。这意味着在每次乘法时,您的数字会变小。因此,当你将它们乘以1000时,它可能与0无法区分。
在某些时候,ruby会将你的数字设为如此之小,以至于它为0.例如:2.0e-1000 # => 0
答案 1 :(得分:1)
每次乘法都会使你的数量减少大约 1/2 1 ,所以在大约50次之后,你会减少 1/2 50 < / sup>,,在100000之后(实际上,在大约700之后),你有 underflowed FP format itself, see here.
答案 2 :(得分: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_000
decimals.reduce :*
电话在我的计算机上停留了几分钟,然后我终于打断了它。