重複の可能性:floatとfloatリテラルの比較における、
floatとdoubleの比較の奇妙な出力の最も効果的な方法
int main()
{
float a = 0.8;
if (a == 0.8)
printf("x\n");
else
printf("y\n");
return 0;
}
aは0.8ですが、 y を出力します。
重複の可能性:floatとfloatリテラルの比較における、
floatとdoubleの比較の奇妙な出力の最も効果的な方法
int main()
{
float a = 0.8;
if (a == 0.8)
printf("x\n");
else
printf("y\n");
return 0;
}
aは0.8ですが、 y を出力します。
0.8 は、2 進浮動小数点では正確に表すことができません。コードif (a == 0.8)
は基本的に、単精度 0.8 と倍精度 0.8 を比較しますが、これらは等しくありません。
これを自分で確認するには、次のコードを試してください。
int main()
{
double a = 0.8f;
double b = 0.8;
printf("%lX\n", *(long *)&a);
printf("%lX\n", *(long *)&b);
}
以下を出力します。
3FE99999A0000000
3FE999999999999A
if (a==0.8f)
代わりにこれを試してください。デフォルトでは、型は double と見なされ、比較すると精度エラーがあります。
リテラルの 0.8 を使用していますが、必ずしも浮動小数点数であるとは限りません。使用してみてください:
if (a==0.8F)
代わりは
また、数値の小数部分を表すことは、コンピューターが内部で基数 2 を使用しているため、エラーが発生しやすいことで有名です。
浮動小数点数は正確な値ではありません。== と != を使用してそれらを比較することは想定されていません。大なり演算子と小なり演算子を適度に小さいイプシロンで使用します。
if ((a > 0.79) && (a < 0.81))
フロートは常に100%正確であるとは限りません。保存方法が原因で、フロートが正確であるとは限りません。あなたが言うならfloat a = 0.8
、aは本当にそうかもしれない0.800000000001
かそのようなものかもしれません。これを補うために、ある種のしきい値を使用する必要があります。if (fabs(a-0.8) < 1.0e-5)
代わりに試してください
浮動小数点数の場合、0.8は実際には0.8を意味しませんが、0.799999999であるため、発生
します。なぜ
0.79999999であるか
これは、浮動小数点値の格納に依存します。10進値は、バイナリ形式(....、2 ^ 3,2 ^ 2,2 ^ 1,2 ^ 0、。、2 ^ -1,2 ^ -2,2 ^ -3、。。 。)
したがって、0.8が2の倍数で.101b(0.8ではなく0.799999988)として格納される場合、その値は0.8未満になります。
if (a > 0.8)
それもFalse
理由です。
あなたの結果のために試してみてください
if (a == 0.8f)
これは、浮動小数点が 10 進数を正確に表すことができないため、正確に 0.8 ではないためです。そして、浮動小数点数として丸められた 0.8 と小数として丸められた 0.8 を比較していますが、必ずしも同じではありません。
異なるタイプの 2 つの値を比較しています: a
is of type float
、0.8
is of type double
。
比較の前に、float
値はdouble
... に変換されますが、からの変換double
とfloat
その逆の変換では、必ずしも同じ値が得られるとは限りません
if (0.8 == (double)(float)0.8) /* ... */