2014年8月27日水曜日

浮動小数点数の怖い話

プログラミングで浮動小数点数を取り扱う場合、
思わぬところで丸め誤差の影響がでて、バグが発生することがあります。

ここでは3つの事例を記録しておきます。

その1

---ソース(一部)---
double d;
for(d=0.0; d<1.0; d+=0.1){
 printf("d=%f\n",d);
}

---実行結果---
d=0.000000
d=0.100000
d=0.200000
d=0.300000
d=0.400000
d=0.500000
d=0.600000
d=0.700000
d=0.800000
d=0.900000
d=1.000000
---

0.1を10回足すと、表示上は1.0になりますが、
実際には1.0よりわずかに小さいためにd<1.0の条件を満たします。



その2.

---ソース(一部)---
printf("(int)(0.000140/0.000020)=%d\n",(int)(0.000140/0.000020));

---実行結果---
(int)(0.000140/0.000020)=6
---

割り算の結果が7よりわずかに小さくなる。



その3.

---ソース(一部)---
double a=0.1271;
printf("(int)(0.1271*10000)=%d\n",(int)(a*10000));

---実行結果---
(int)(0.1271*10000)=1270
---

これも掛け算の結果が1271よりわずかに小さいのでしょう。
ただし、私の環境では、
(int)(a*10000)の代わりに(int)(0.1271*10000)とするとちゃんと1271になります。




本当に怖い。
これはC言語に限った話ではないような気がしますが、どうでしょう。

0 件のコメント:

コメントを投稿