• ベストアンサー

浮動小数点演算でのエラー

下記のようなスクリプトを実行したところ 計算結果がうまく表現されてません。 ####スクリプトの中身(tmp.plx)#### #!/usr/local/bin/perl -w use strict ; my $x = 38.475 ; foreach ( 0..21 ){ $x += 0.495 ; print $x . "\n" ; } ####実行結果#### tmp.plx 38.97 39.465 39.96 40.455 40.95 41.445 41.94 42.435 42.93 43.425 43.92 44.415 44.91 45.405 45.9 46.395 46.89 47.385 47.88 48.375 48.8699999999999 #<=ここで本来48.87 49.3649999999999 #######ここまで 期待値が48.87と出て欲しいところ 上記のような結果となります。 2進数での計算が浮動小数点を完全に表現することができない ことはわかるのですが、 $a=48.375; $a+=+0.495 ; print $a . "\n" ; # 48.87を表示 と単体での計算が正しい結果が出るのが理解できません。 どうしてなのでしょうか?

質問者が選んだベストアンサー

  • ベストアンサー
noname#26652
noname#26652
回答No.1

0.495という数値は、実際にはたぶん0.495よりもごくわずかに 小さな値としてコンピュータは記憶しているのでありましょう。 例えば0.49499999999999999あたりのように。 くだんのループの終盤に来るまでは、そのわずかな誤差の累積が 計算結果に影響を与えるほどではなかったのだと思います。 ところが、ループの終盤、誤差の累積が計算結果に影響を与えるほど 大きくなり、最後の2行のようになったのだと思います。

renkado
質問者

お礼

なるほど、納得です。 ありがとうございました。

その他の回答 (1)

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.2

#1の方の回答ですんじゃってますが補足として。 > $a=48.375; > $a+=+0.495 ; > print $a . "\n" ; # 48.87を表示 > と単体での計算が正しい結果が出るのが理解できません。 これは、二進による内部表現から十進表記に変換するときに使用している 書式の影響による丸めのために、一見正しい値になっているように見えているだけです。 C:\home>perl -d -e0 Loading DB routines from perl5db.pl version 1.28 Editor support available. Enter h or `h h' for help, or `perldoc perldebug' for more help. main::(-e:1): 0 DB<1> $x = 48.375 DB<2> print $x+0.495 48.87 DB<3> printf "%20.18f", $x+0.495 48.869999999999997000 DB<4> DB<3>の出力にあるように、内部的には 48.87 という値にはなっていないのです。

renkado
質問者

お礼

解説ありがとうございます。 たまたま浮動小数点計算でうまくいかなくなったことが とても勉強になりました。

関連するQ&A

専門家に質問してみよう