0.1 を 10回足しても 1.0 にならない!? ~ double の不思議

double は 8バイト=64 ビットで、10 桁以上(15桁)の精度を持つ浮動小数点数です。

10 桁以上と計算には十分な精度を持っていながら、同時にちょっと困った性質も持っています。

0 で初期化された double の変数に 0.1 を 10 回足しても、1.0 にならないのです。
どういう事かというと、次のようなコードを実行した場合、、、

    double d = 0;
    for(int i=0; i<10; i++)
    {
        d += 0.1;
    }
    if(d == 1.0)
    {
        printf("%f = %f -- same\n", d, 1.0);
    }
    else
    {
        printf("%10.20f != %10.20f -- differ\n", d, 1.0);
    }


結果は以下のようになります。


0.99999999999999989000 != 1.00000000000000000000 -- differ


なぜこのような事が起こるのか、、、

試しに、 0.1 を printf("0.1 is %10.20f\n", 0.1); として確認してみると、次のようになりました。


0.1 is 0.10000000000000001000


むむむ!

浮動小数点数の 0.1 は リアル0.1 よりも 0.00000000000000001 大きいにもかかわらず、10回足し合わせると リアル1.0 よりも小さくなってしまいます。

何とも不可思議です。

その理由は、2進数にあります。
2進数では、小数点数を表現するのが苦手なのです。
小数点数はやむを得ず近似されてしまうのです。
暇な人は調べてみてください。

有効桁数15桁までは正しい事には変わりありませんから、文句も言えません。

このように、いくら精度が良くても、計算結果が近似値になってしまうとなると、困った問題が発生する事があります。
特に、このプログラムのように = で値を評価しようとすると、予測値と計算値が = となることは滅多に無い事になってしまいます。

double(浮動小数点) で値を = で評価したいときには、誤差範囲 ±α を見込んだ比較関数を作成して、誤差範囲に入っているかどうかで 比較演算を行う必要がありそうです。
[PR]
by isoq | 2006-04-18 13:18 | C/C++/Win32
e87.com(千趣会イイハナ) 花を贈るなら日比谷花壇
<< MFCで発生するリンクエラー ... PC不安定・インストール失敗の... >>