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/21減少するため、約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_000するdecimals.reduce :*と、コンピュータで数分間通話が続いた後、最終的に通話が中断されました。

于 2013-01-11T22:10:10.733 に答える