14歳の自分に衝撃の事実を告げてください

C言語入門者です。
Doubleの比較方法がどうしても解りませんので教えていただけますでしょうか。

double num = 28.0*(87.0/84.0);

この計算したものをif文内で29.0と比較するとおかしな結果になります
以下のプログラムはBと出力されます

これを正しく比較するにはどうしたらいいでしょうか?

よろしくお願いします

int main() {
double a=28.0, b=29.0, x=87.0/84.0;

printf("%lf\n", 28.0*87.0/84.0);
if (a*x==b) {
printf("A\n");
} else if (a*x>b) {
printf("B\n");
}
}

A 回答 (3件)

double型での計算では誤差が発生します。


(浮動小数点数とかで検索すると詳しい説明が出てくると思います。)

a*xの計算結果は、誤差によって29とちょっとだけずれた値になっているはずです。
4行目のprintfを次のようにするとちょっと違う部分が見えてくると思います。
 printf("%0.16f\n", 28.0*(87.0/84.0));

28.0*87.0/84.0と、28.0*(87.0/84.0) では誤差の出方が違う点にも注意が必要です。
28.0*(87.0/84.0)の計算順序にしないと、a*xとはちょっとだけ違う値になります。

値が同じかどうかを正しく比較するには、どうなっていれば「正しい比較」なのかが重要になります。
例えば小数点以下6桁くらいまで合っていれば同じと見なして良い状況では、2つの値の差の絶対値が0.000001以下なら同じと判定できます。
これは何のために比較をするのかに合わせて検討する必要がある事柄で、どんな場合にも通用する答えという物はありません。
    • good
    • 0
この回答へのお礼

勉強になりました
ありがとうございました。

お礼日時:2019/12/26 18:33

浮動小数点型である double を使う以上は、


誤差の問題が必ず発生するので正確な比較が出来ません。

要件にもよりますが、以下の代案を検討してください。

案1. 演算順序を誤差がでないように配慮する
一般に割り算で誤差が生まれるので、掛け算をしてから割り算をする

案2. 実用上問題のない精度で数値を丸めてから比較する
if (round(a * 1000.0) == round(b * 1000.0))

案3. double 型ではなく有理数型で計算する
https://na-inet.jp/na/gmp_ja/Rational-Number-Fun …
    • good
    • 0
この回答へのお礼

勉強になりました
ありがとうございました。

お礼日時:2019/12/26 18:34

double 比較 誤差


で検索。

その結果は、あなたが「期待する」ものではないですが、コンピュータとしては「正しい」ものです

x=87.0/84.0 は綺麗に割り切れないため、有限桁しかできないdoubleでは途中で止めて 「87.0/84.0の近似値」になっています。
近似値を使った計算をすれば、近似値しか求められません。


○誤差出るものだと諦めて、誤差を考慮した判定をする。
○計算を工夫することで、ある程度は精度よく計算できる
 これの場合だと、x を分子x0と分母x1に分けて使う、とか
    • good
    • 0
この回答へのお礼

ありがとうございました。

お礼日時:2019/12/26 18:34

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


おすすめ情報