次の単体テストを検討してください。
// 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で精度を失うことなく表現できないため)が、これは浮動小数点数では機能し、倍精度数では機能しない理由を説明していません...
誰かがこれを説明できますか?