私が持っている:Rubyの和STDIN整数
$ ruby -v
ruby 2.0.0p648 (2015-12-16 revision 53162) [universal.x86_64-darwin16]
あなたは、整数のシーケンス1..n
ルビー初心者はそうのようなシーケンスを合計うがあるとします。
$ ruby -e 's=0
for i in 1..500000
s+=i
end
puts s'
125000250000
は、今私は、同じ配列を持っていると仮定それはstdin
から来て:
$ seq 1 500000 | ruby -lne 'BEGIN{s=0}
s+=$_.to_i
END{puts s} '
125000250000
これまでのところとても良いです。
は今5,000,000 500,000から端末価値を高める:
は$ ruby -e 's=0
for i in 1..5000000
s+=i
end
puts s'
12500002500000 <=== CORRECT
$ seq 1 5000000 | ruby -lne 'BEGIN{s=0}
s+=$_.to_i
END{puts s} '
500009500025 <=== WRONG!
それは別の合計を生成します。
awk
とperl
の両方が同じ順序で正しい結果を生成します。
$ seq 1 5000000 | awk '{s+=$1} END{print s}'
12500002500000
$ seq 1 5000000 | perl -nle '$s+=$_; END{print $s}'
12500002500000
はなぜルビーが間違っ合計を生産していますか? awk
とperl
が同じ入力に対して正しく機能しているため、オーバーフローしているとは思われません。
結論:
これを診断するためのあなたのデビッド・オルドリッジをありがとうございます。 GNU seq
は、任意精度の整数をサポートしながら
OS XとBSD
seq
は1,000,000でフロート出力に変換します。 OS Xseq
は、1,000,000を超える整数のソースとしては役に立たない。 OS X上の例:$ seq 999999 1000002 999999 1e+06 1e+06 1e+06
サイレント整数に部分文字列を変換し、すなわち、この場合に「バグ」であった
.to_i
ルビー方法。例:irb(main):002:0> '5e+06'.to_i #=> 5
スクリプトで「正しい」ラインは、浮動小数点数を使用するか、スクリプトが黙って失敗していないために
Integer($_)
を使用する$_.to_f.to_i
を使用するかのいずれかです。awk
とperl
解析5E + 06フロートに、とruby
は暗黙的にしません:.to_i
行動に関するルビーfeature requestを開くための$ echo '5e+06' | awk '{print $1+0}' 5000000 $ echo '5e+06' | ruby -lne 'print $_.to_i+0' 5
そしてステファンSchusslerのおかげで。
この問題については、[機能リクエスト](https://bugs.ruby-lang.org/issues/13693)を開設しました。 – Stefan
FWIW Ruby 2.4 Enumerable#sumメソッドはこのために最適化されているので、 '(1..5000000).sum'はほとんど瞬時に戻ります。 – steenslag
なぜ私はこの質問または今後の質問を修正することができますので、投票をなぜ尋ねることができますか?他のRuby初心者のためにここで不明な点や役に立たなかった点がありましたか? – dawg