9
double a = 18.565
return Math.Round(a,2)

..18.57 を返します。
私が試した他のすべての数値について、銀行家の丸めは期待どおりに機能しました。たとえば、Math.Round(2.565,2) は 2.56 を返しました。

なぜ、いつそれが起こるのか手がかりはありますか?エラーですか、それともバンカーの丸めに関する何かが欠けていますか?

ありがとう..

4

4 に答える 4

17

マシューが言ったように、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
于 2010-09-23T06:13:32.267 に答える
5

18.565をdoubleとして正確に表すことはできません。したがって、バイナリ表現はわずかに高いため、切り上げられます。10進数を使用する場合:

decimal a = 18.565m;
return Math.Round(a,2)

正確に表現でき、この問題は発生しません。

于 2010-09-23T06:11:23.470 に答える
1

私の推測では、FP表現は、実際には末尾の5ではないことを意味します。FPの危険性!

ただし、これは正常に機能します。

        decimal a = 18.565M; // <===== decimal
        var s = Math.Round(a, 2);
于 2010-09-23T06:13:39.847 に答える
0

Doubleは浮動小数点値であるため、18.565と書くと、実際には18.56500000000000000000000000000000001のようにメモリ内にあるため、中点を超えています。

于 2010-09-23T06:14:02.327 に答える