none
double型の除算結果の相違について RRS feed

  • 質問

  • お世話になります。
    vc6.0でc言語の開発環境です。

    double型の値を除算するとき、除算方法によって計算結果が少し異なって算出されます。

    除算方法(1) double型の値を1000000で除算
    除算方法(2) double型の値を10で除算×6回

    ソースは下記の通りです。

    #include <stdio.h>
    void main()
    {
        double x;
         int i;
         x = 2356220000.;
         x /= 1000000;
         printf( "除算方法(1)   %.15f\n",x);

         x = 2356220000.;
         for( i=0;i<6;i++){
              x /= 10;
         }
         printf( "除算方法(2)   %.15f",x );
    }

    ソースここまで。

    このソースを実行すると
    除算方法(1)   2356.219999999999800
    除算方法(2)   2356.220000000000300
    と表示されます。

    どちらもdouble型の値を100万分1にしていますが、若干ですが差異が発生します。
    この理由をご存じのかた、教えてください。
    浮動小数点数の近似値的表現が原因でしょうか?

    よろしくお願いします。

    2006年11月1日 13:52

すべての返信

  • >浮動小数点数の近似値的表現が原因でしょうか?

    そうでしょう。

    それくらいの誤差で困る場合にはDecimalをどうぞ。

    あくまでdoubleはアバウトな数値です。

    2006年11月1日 13:58
  •  中博俊 さんからの引用

    それくらいの誤差で困る場合にはDecimalをどうぞ。

    ってことでDecimalを使ったサンプルです。
    ただし、DecimalはWindowsの型です。(->windows.hをインクルードする必要がある)
    標準のC/C++では確かそういうデータ型はなかった気がします。(ない場合は自作でしょうか。骨折れそう)
    #include <windows.h>
    #include <locale.h>
    #include <stdio.h>
    
    int main(void)
    {
        DECIMAL x, y, z;
        BSTR result;
    
        setlocale(LC_ALL, "Japanese"); /* wprintfのため */
        
        VarDecFromUI4(2356220000ul, &x);
        VarDecFromUI4(1000000ul, &y);
    
        /* z = x / y; */
        VarDecDiv(&x, &y, &z);
    
        VarBstrFromDec(&z, LOCALE_USER_DEFAULT, 0, &result);
        wprintf(L"結果 %s\n", result);
        SysFreeString(result);
    
        return 0;
    }
    参考:ら ら ら のプログラマーズラウンジ - 割り算について
    2006年11月1日 14:32
  • 中博俊さん、蒼の洞窟さん、回答ありがとうございます。

    実は、このdouble型の変数をいろいろ計算して
    その計算結果が期待したものと異なっていたので、
    悩んでいました。
    最初は、CPUのアーキテクチャの問題(double型専用の計算回路)なのか、
    変数が確保されているスタック領域の問題なのか、
    はたまた、浮動少数点数の除算ロジックが原因なのか、
    いろいろ考えていました。


    計算結果の精度を上げるフローを考えるのは難しいです・・・。

    #   Decimalは使用したことはないですが、この三連休で勉強してみます。

    2006年11月2日 17:03