舍入小数值

时间:2012-07-31 13:17:12

标签: c# floating-point

使用Math.Round(a, 2);

在C#中舍入十进制值时遇到问题

当我将1.275舍入2小数点时,结果为1.27。 当我为1.375做同样的事情时,结果是1.38。

为什么它不会将1.275舍入到1.28?

由于

7 个答案:

答案 0 :(得分:8)

我无法重现您的问题:

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

我怀疑您声称使用decimal值的说法是错误的,而您使用的是double值。 double无法准确表示多个十进制值,因此当您编写1.275时,它实际上是1.27499 ... 1.375是为数不多的可表示的一个,所以它实际上是{{1} }。

如果您的代码关心精确的十进制表示,例如当您处理金钱时,必须使用1.375而不是二进制浮点,例如decimal或{{ 1}}。


但即使您使用十进制表示,对于许多用户来说,舍入行为也会出乎意料:

double

默认情况下,float使用MidpointRounding.ToEven,也称为Banker's round。这样可以避免在Math.Round(1.265m, 2) => 1.26m Math.Round(1.275m, 2) => 1.28m 总是向上舍入时产生偏差。

您可以使用采用舍入模式的Math.Round重载,并将其设置为.5以获得您期望的行为。

Round

答案 1 :(得分:7)

MSDN对此行为有这样的说法:

  

来电者须知

     

由于可能导致精度损失   将十进制值表示为浮点数或执行   浮点值的算术运算,在某些情况下是   Round(Double,Int32)方法可能看起来不是圆中点值   小数位数中最接近的偶数值。这是   如下例所示,其中2.135舍入为2.13   而不是2.14。发生这种情况是因为内部方法相乘   值为10 digits ,以及这种情况下的乘法运算   失去精确度。

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

答案 2 :(得分:4)

如果您的值为Decimal,则会将1.275正确地舍入1.28

如果您有Double值,则其行为不会相同,因为无法准确表示值1.275。如果您使用double1.275,它实际上会比确切的值1.275略小,例如1.2749999999999999

在对该值进行舍入时,1.271.28之间不会很明显,但会更接近1.27,因此它将向下舍入而不是向上。

答案 3 :(得分:2)

这是一个可怕的黑客,但尝试使用格式。它莫名其妙地使用我们都习惯的舍入。

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

(OR)

仅供参考:从.Net 2.0版开始,可以定义使用参数MidpointRounding对“0.5个案例”进行舍入的方式。它可以是ToEven或AwayFromZero。所以“标准”舍入将是这样的:

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

这将返回值“2.3”。

答案 4 :(得分: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

答案 5 :(得分:1)

这是因为你的舍入是双精度而不是小数:

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

十进制和双打是非常不同的

答案 6 :(得分:0)

根据文档的预期行为。

  

例如,如果小数等于1,则2.15和2.15000都是   舍入到2.2因为.05和.05000都在.1和。之间   .2和.1是奇数。同样,如果小数等于1,则为2.05和   2.05000都被舍入到2.0,因为.05和.05000都在.0和.1之间,而.0是偶数。这个行为   方法遵循IEEE标准754第4节。这种舍入是   有时被称为舍入到最近,或银行家的四舍五入。它   最小化由于始终舍入a而导致的舍入误差   单个方向的中点值。控制的类型   Round(Decimal,Int32)方法使用的舍入,调用   Decimal.Round(Decimal,Int32,MidpointRounding)重载。

来自Math.Round(decimal, int)。尝试

Decimal.Round(a, 2, MidpointRounding.AwayFromZero);