web-dev-qa-db-ja.com

なぜ0.1 + 0.2 == 0.3がDなのか?

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 に感謝します。これは there で説明されている浮動小数点定数の折りたたみの効果です。

コード:

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

75
Stas

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

47
Flynn1179

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


あなたのコードの浮動小数点の不正確さは決定的であり、予測できない間違い(ある意味、あなたのアプローチは、浮動を理解していない人々のアプローチとは正反対です)と仮定しているようですまだポイント)。

(Benが指摘しているように)浮動小数点の不正確さis決定論的ですが、コードの観点からは、すべてのステップで値に何が起きているのかについて非常に慎重になっていない場合、そうです。任意の数の要因により、0.1 + 0.2 == 0.3が成功し、コンパイル時の最適化が1つ、リテラルが別の値に微調整されます。

ここに頼ってくださいneither成功時でも失敗時でも;浮動小数点の等値に依存しないでくださいどちらの方法でも

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

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

5
Jean Hominal