double a = 18.565
return Math.Round(a,2)
..18.57 を返します。
私が試した他のすべての数値について、銀行家の丸めは期待どおりに機能しました。たとえば、Math.Round(2.565,2) は 2.56 を返しました。
なぜ、いつそれが起こるのか手がかりはありますか?エラーですか、それともバンカーの丸めに関する何かが欠けていますか?
ありがとう..
double a = 18.565
return Math.Round(a,2)
..18.57 を返します。
私が試した他のすべての数値について、銀行家の丸めは期待どおりに機能しました。たとえば、Math.Round(2.565,2) は 2.56 を返しました。
なぜ、いつそれが起こるのか手がかりはありますか?エラーですか、それともバンカーの丸めに関する何かが欠けていますか?
ありがとう..
マシューが言ったように、18.565は正確に表現することはできません。使用される実際の値は18.565000000000001278976924368180334568023681640625( DoubleConverterを使用して検出)であり、明らかに半分を超えています。今、私は時々、実際には中間点を超えているが、正確に表現できる限り中間点に近い値を、正確にその点にある Math.Round
と見なすというこっそりした感じがします。ただし、それが適用される状況を説明するドキュメントは見たことがなく、この場合は明らかに発生していません。私はそれに頼りたくありません。
もちろん、四捨五入された値でさえ正確に18.57ではありません。実際には18.57000000000000028421709430404007434844970703125です。
基本的に、10進値を正確に表現することに本当に関心がある場合は、を使用する必要がありますdecimal
。これは、Math.Round
浮動小数点値の処理のあらゆる側面に当てはまります。
もちろん、それは正しい価値を与えます:Math.Round
decimal m = 18.565m;
Console.WriteLine(Math.Round(m, 2)); // Prints 18.56
18.565をdoubleとして正確に表すことはできません。したがって、バイナリ表現はわずかに高いため、切り上げられます。10進数を使用する場合:
decimal a = 18.565m;
return Math.Round(a,2)
正確に表現でき、この問題は発生しません。
私の推測では、FP表現は、実際には末尾の5ではないことを意味します。FPの危険性!
ただし、これは正常に機能します。
decimal a = 18.565M; // <===== decimal
var s = Math.Round(a, 2);
Doubleは浮動小数点値であるため、18.565と書くと、実際には18.56500000000000000000000000000000001のようにメモリ内にあるため、中点を超えています。