4

次の単体テストを検討してください。

// Works (sum 0.1 to 0.4)
float f1 = 0.1F + 0.2F + 0.3F + 0.4F;
Assert.AreEqual(1F, f1);

// Works too (sum 0.4 to 0.1)
float f2 = 0.4F + 0.3F + 0.2F + 0.1F;
Assert.AreEqual(1F, f2);

// Works (sum 0.1 to 0.4)
double d1 = 0.1D + 0.2D + 0.3D + 0.4D;
Assert.AreEqual(1D, d1);

// Fails! (sum 0.4 to 0.1)
double d2 = 0.4D + 0.3D + 0.2D + 0.1D;
Assert.AreEqual(1D, d2);

float 型の場合はすべてが期待どおりに機能しますが (どちらの場合も合計は 1 です)、double を使用する場合、加算の可換性は考慮されません。実際、最初の合計は 1 ですが、2 番目の合計は 0.99999999 になります.....

結果が1回で1回ではない理由を理解しています(一部の数値は基数2で精度を失うことなく表現できないため)が、これは浮動小数点数では機能し、倍精度数では機能しない理由を説明していません...

誰かがこれを説明できますか?

4

4 に答える 4

1

以下では:

float f = 0.3F + 0.3F + 0.2F + 0.1F;
double d = 0.3D + 0.3D + 0.2D + 0.1D;

結果は次のようになります。

float f = 0.900000036f;
double d = 0.9;

したがって、数値が異なると、浮動小数点数では丸め誤差が発生し、倍精度浮動小数点数では丸め誤差が発生する可能性があります。これは、桁数が異なるため、丸め誤差が発生する場所が異なるためです。

于 2013-05-28T09:07:13.163 に答える
0

これは、浮動小数点数を比較する際の既知の問題です。C# 仕様によると、浮動小数点数は、この動作を引き起こす厄介な IEEE 標準に基づいて実装されているためです。

したがって、C# で 2 つの float または double を比較する必要はありません。代わりに、それらの差が特定のデルタ値よりも小さいかどうかを確認する必要があります。

于 2013-05-28T10:35:51.183 に答える