8

を使用してC#で10進値を丸めているときに問題に直面していますMath.Round(a, 2);

1.275 を小数点以下 2 桁で四捨五入すると、結果は 1.27 になります。1.375 に対して同じことをすると、結果は 1.38 になります。

1.275 を 1.28 に丸めないのはなぜですか?

ありがとう

4

7 に答える 7

8

問題を再現できません:

Math.Round(1.275m, 2) => 1.28m
Math.Round(1.375m, 2) => 1.38m

値を使用しているというあなたの主張decimalは誤りであり、double代わりに値を使用していると思われます。double多くの 10 進数値を正確に表すことはできないため、 と書く1.275と、実際には 1.27499 になります...1.375 は数少ない表現可能な 1 回の 1 つなので、実際には1.375.

コードで正確な 10 進数表現が重要な場合 (たとえば、お金を扱う場合)、やなどの 2 進浮動小数点ではなく、使用する必要があります。decimaldoublefloat


しかし、10 進数表現を使用しても、丸めは多くのユーザーにとって予期しない動作をします。

Math.Round(1.265m, 2) => 1.26m
Math.Round(1.275m, 2) => 1.28m

デフォルトでMath.Roundは、バンカーのラウンドMidpointRounding.ToEvenとも呼ばれる を使用します。これにより、常に で切り上げられることによるバイアスの蓄積が回避されます。.5

Round丸めモードを取るのオーバーロードを使用し、それを に設定してAwayFromZero、期待どおりの動作を得ることができます。

Math.Round(1.275m, 2, MidpointRounding.AwayFromZero) => 1.28m
于 2012-07-31T13:19:16.830 に答える
7

MSDNは、この動作に関して次のように述べています。

発信者への注意事項

10 進数値を浮動小数点数として表現したり、浮動小数点値に対して算術演算を実行したりすると、精度が失われる可能性があるため、場合によっては、Round(Double, Int32) メソッドが中間値を最も近い偶数に丸めるように見えないことがあります。小数点以下桁数の値。これは、2.135 が 2.14 ではなく 2.13 に丸められる次の例に示されています。これは、メソッドが内部で value を 10で乗算するために発生し、この場合の乗算演算は精度の損失に悩まされます。

public class Example
{
   public static void Main()
   {
      double[] values = { 2.125, 2.135, 2.145, 3.125, 3.135, 3.145 };
      foreach (double value in values)
         Console.WriteLine("{0} --> {1}", value, Math.Round(value, 2));

   }
}
// The example displays the following output:
//       2.125 --> 2.12
//       2.135 --> 2.13
//       2.145 --> 2.14
//       3.125 --> 3.12
//       3.135 --> 3.14
//       3.145 --> 3.14
于 2012-07-31T13:27:46.010 に答える
4

値があるDecimal場合、正しく丸め1.275られ1.28ます。

値があるDouble場合、値1.275を正確に表すことができないため、同じようには動作しません。doubleこの値を使用する1.275と、実際には正確な値よりもわずかに小さくなり1.275ます1.2749999999999999

その値を四捨五入すると、正確に と の間1.27ではなく1.28、わずかに に近づくため1.27、切り上げではなく切り捨てられます。

于 2012-07-31T13:28:18.307 に答える
2

これはひどいハックですが、Format を使用してみてください。不可解なことに、私たち全員が慣れ親しんでいる丸めを使用しています。

Val(Format(2.25, "0.0")) returns 2.3

(また)

参考までに: .Net バージョン 2.0 から、"0.5 ケース" をパラメータ MidpointRounding で丸める方法を定義することが可能になりました。ToEven または AwayFromZero のいずれかです。したがって、「標準」の丸めは次のようになります。

Math.Round(2.25, 1, MidpointRounding.AwayFromZero);

これは、値「2.3」を返します。

于 2012-07-31T13:23:15.843 に答える
1

これは、丸めが小数ではなく倍精度であるためです。

Console.WriteLine(Math.Round(1.275M, 2)); // outputs 1.28
Console.WriteLine(Math.Round(1.375M, 2)); // outputs 1.38

Decimal と double は大きく異なります

于 2012-07-31T13:28:46.907 に答える
1
Format(1.275, "0.00")) 

このブログのコメントで示唆されているように: http://weblogs.asp.net/sfurman/archive/2003/03/07/3537.aspx

どのバージョンの .Net フレームワークを使用していますか? 1.1 を超える場合は、midpointroundingを使用して、次のように設定できます。AwayFromZero

Math.Round(1.275, 2, MidpointRounding.AwayFromZero);

http://msdn.microsoft.com/en-us/library/9s0xa85y%28v=vs.110%29.aspx

于 2012-07-31T13:20:25.207 に答える
0

ドキュメントに従って予想される動作。

たとえば、小数が 1 に等しい場合、.05 と .05000 はどちらも .1 と .2 の中間にあり、.1 は奇数であるため、2.15 と 2.15000 は両方とも 2.2 に丸められます。同様に、小数が 1 に等しい場合、.05 と .05000 はどちらも .0 と .1 の中間にあり、.0 は偶数であるため、2.05 と 2.05000 は両方とも 2.0 に丸められます。このメソッドの動作は、IEEE 規格 754 のセクション 4 に従います。中間値を一方向に一貫して丸めることに起因する丸め誤差を最小限に抑えます。Round(Decimal, Int32) メソッドで使用される丸めの種類を制御するには、Decimal.Round(Decimal, Int32, MidpointRounding) オーバーロードを呼び出します。

Math.Round(decimal, int)から。試す

Decimal.Round(a, 2, MidpointRounding.AwayFromZero);
于 2012-07-31T13:55:02.297 に答える