プロが教えるわが家の防犯対策術!

ループで小数を使うと変な誤差が出るので困っています。例えば、以下のプログラムを実行します。
for(my $i = -2; $i <= 2; $i += 0.01){ print "$i\n"; }
結果の一部だけを抜粋すると、以下のように微妙に誤差のある出力部分が所々にあります。
-0.0199999999999984
-0.00999999999999836
1.64104840827406e-15
0.0100000000000016
この誤差が非常に気になります。
とりあえず、その場しのぎで、
use POSIX;
for(my $i = -2; $i <= 2; $i += 0.01){ print floor(($i + 0.005)*100)/100 . "\n"; }
として回避していますが、根本的な解決になっていないような気がして気持ち悪い思いをしています。

質問は2種類です。
・なぜ、この誤差が生じるのでしょうか?
・この誤差を生じないようにするモジュールや、解決法などはありませんか?

A 回答 (3件)

つい最近、別のカテゴリですが同様の質問がありました。



MSN相談箱 なぜ最後の数値が出ませんか
http://questionbox.msn.co.jp/qa2829383.html

Math::BitFloatとかMath::BigRatを使うと
解決できるかもしれません。
    • good
    • 0
この回答へのお礼

大変有用な回答をありがとうございました。
おかげ様で、解決できました。

問題のプログラムですが、ご提案にあったMath::BigFloatを使って以下のようにすることで解決しました。
use Math::BigFloat;
my $step = Math::BigFloat->new('0.01');
for(my $i = -0.5; $i <= 0.5; $i += $step){ print "$i\n"; }

お礼日時:2007/03/16 12:14

#2ですが。

ちょっとつけたし。

> Math::BigFloatを使って以下のようにすることで解決しました。

誤差の解消という面ではBigFloatを使うということで
問題ないと思いますが、ループの制御変数などに使うと
(BigFloatの処理は「重い」ので)処理速度に影響が
でます。

使いどころには気をつけてください。
    • good
    • 0
この回答へのお礼

アドバイスをありがとうございます。
参考になりました。
よく考えて使ってみることにします。

お礼日時:2007/03/16 20:27

1番目だけ:小数点以下の値での2進数と10進数での変換時の誤差かと思います。


10進数の0.1は2進数では無限小数になります。
    • good
    • 0
この回答へのお礼

素早い回答ありがとうございます。
疑問が解けました。ありがとうございます。

お礼日時:2007/03/16 11:50

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!