75
assert(0.1 + 0.2 != 0.3); // shall be true

言語がネイティブ浮動小数点演算を使用していることを確認するのが私のお気に入りです。

C ++

#include <cstdio>

int main()
{
   printf("%d\n", (0.1 + 0.2 != 0.3));
   return 0;
}

出力:

1

http://ideone.com/ErBMd

Python

print(0.1 + 0.2 != 0.3)

出力:

True

http://ideone.com/TuKsd

その他の例

なぜこれはDには当てはまらないのですか?理解しているように、Dはネイティブの浮動小数点数を使用します。これはバグですか?特定の数値表現を使用していますか?他に何かありますか?かなり紛らわしい。

D

import std.stdio;

void main()
{
   writeln(0.1 + 0.2 != 0.3);
}

出力:

false

http://ideone.com/mX6zF


アップデート

LukeHに感謝します。これは、そこで説明されている浮動小数点定数畳み込みの効果です。

コード:

import std.stdio;

void main()
{
   writeln(0.1 + 0.2 != 0.3); // constant folding is done in real precision

   auto a = 0.1;
   auto b = 0.2;
   writeln(a + b != 0.3);     // standard calculation in double precision
}

出力:

false
true

http://ideone.com/z6ZLk

4

3 に答える 3

53

(フリンの答えは正解です。これはより一般的に問題に対処します。)


OPは、コード内の浮動小数点の不正確さが決定論的であり、予測どおりに間違っていると想定しているようです(ある意味で、あなたのアプローチは、浮動小数点をまだ理解していない人のアプローチとは正反対です)。

(Benが指摘しているように)浮動小数点の不正確さ決定論的ですが、コードの観点からは、すべてのステップで値に何が起こっているかについてあまり慎重に考えていなければ、そうではありません。いくつもの要因が成功につながる可能性があり0.1 + 0.2 == 0.3、コンパイル時の最適化は1つであり、それらのリテラルの値を微調整すると別の値になります。

ここでは成功にも失敗にも頼らないでください。どちらの方法でも浮動小数点の等式に依存しないでください。

于 2011-07-29T14:21:19.667 に答える
47

おそらく(0.3!= 0.3)に最適化されています。これは明らかに誤りです。最適化設定を確認し、オフになっていることを確認して、再試行してください。

于 2011-07-29T14:06:49.837 に答える
5

D言語仕様の私の解釈によると、x86での浮動小数点演算は、64ビットだけではなく、内部で80ビットの精度を使用します。

しかし、それがあなたが観察した結果を説明するのに十分であることを確認する必要があります。

于 2011-07-29T14:14:44.017 に答える