サーチ…


浮動小数点数は奇妙です

ほとんどすべてのプログラマーが最初に間違いを犯すのは、このコードが意図したとおりに動作することを前提としています。

float total = 0;
for(float a = 0; a != 2; a += 0.01f) {
    total += a;
}

初心者のプログラマは0, 0.01, 0.02, 0.03, ..., 1.97, 1.98, 1.99の範囲内のすべての単一の数値を合計して結果199を得ると仮定します。これは数学的に正解です。

これを真実に見せかける2つのことが起こります:

  1. 書かれたプログラムは決して終わらない。 aは決して2に等しくなく、ループは決して終了しません。
  2. 代わりにa < 2をチェックa < 2ループロジックを書き換えると、ループは終了しますが、合計は199とは異なる値になります。 IEEE754に準拠しているマシンでは、多くの場合約201が加算されます。

これが発生する理由は、 浮動小数点数が割り当てられた値の近似を表すためです

古典的な例は、次の計算です。

double a = 0.1;
double b = 0.2;
double c = 0.3;
if(a + b == c)
    //This never prints on IEEE754-compliant machines
    std::cout << "This Computer is Magic!" << std::endl; 
else
    std::cout << "This Computer is pretty normal, all things considered." << std::endl;

プログラマが見るものは、base10で書かれた3つの数字ですが、コンパイラ(とその基礎となるハードウェア)にはバイナリの数字があります。ので、 0.10.2 、および0.3完全除算必要と10ベース2の基地-10システムでは非常に簡単である-whichが、不可能をシステムこれらの数字は同様に、不正確な形式で格納する必要がどのように数1/3は、基数10の不正確な形式0.333333333333333...に格納する0.333333333333333...

//64-bit floats have 53 digits of precision, including the whole-number-part.
double a =     0011111110111001100110011001100110011001100110011001100110011010; //imperfect representation of 0.1
double b =     0011111111001001100110011001100110011001100110011001100110011010; //imperfect representation of 0.2
double c =     0011111111010011001100110011001100110011001100110011001100110011; //imperfect representation of 0.3
double a + b = 0011111111010011001100110011001100110011001100110011001100110100; //Note that this is not quite equal to the "canonical" 0.3!


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow