C# 四舍五入十进制值

C# 四舍五入十进制值,c#,floating-point,C#,Floating Point,在使用Math.Round(a,2)对C#中的十进制值进行舍入时,我遇到了一个问题 当我将1.275四舍五入2个小数点时,结果是1.27。 当我对1.375做同样的计算时,结果是1.38 为什么不把1.275四舍五入到1.28 谢谢我无法重现您的问题: Math.Round(1.275m, 2) => 1.28m Math.Round(1.375m, 2) => 1.38m 我怀疑您声称使用的是十进制值是错误的,您使用的是双精度值double不能精确地表示许多十进制值,因此当您编写

在使用
Math.Round(a,2)对C#中的十进制值进行舍入时,我遇到了一个问题

当我将1.275四舍五入2个小数点时,结果是1.27。 当我对1.375做同样的计算时,结果是1.38

为什么不把1.275四舍五入到1.28


谢谢

我无法重现您的问题:

Math.Round(1.275m, 2) => 1.28m
Math.Round(1.375m, 2) => 1.38m
我怀疑您声称使用的是
十进制
值是错误的,您使用的是
双精度
double
不能精确地表示许多十进制值,因此当您编写
1.275
时,它实际上是1.27499
1.375
是为数不多的几个有代表性的ONCE之一,因此它实际上是
1.375

如果您的代码关心精确的十进制表示,例如,当您处理货币时,您必须使用
十进制
,而不是二进制浮点,例如
双精度
浮点


但即使使用十进制表示法,舍入对许多用户的行为也是出人意料的:

Math.Round(1.265m, 2) => 1.26m
Math.Round(1.275m, 2) => 1.28m
默认情况下,
Math.Round
使用,也称为。这避免了由于总是在
.5
处四舍五入而累积偏差

您可以使用采用舍入模式的
Round
重载,并将其设置为
AwayFromZero
,以获得预期的行为

Math.Round(1.275m, 2, MidpointRounding.AwayFromZero) => 1.28m
正如本博客评论中所建议的:

您使用哪个版本的.Net framework?如果大于1.1,您可以使用并将其设置为
AwayFromZero

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

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

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

仅供参考:从.Net 2.0版开始,可以使用参数中点舍入来定义“0.5个案例”的舍入方式。它可以是ToEven,也可以是AwayFromZero。所以“标准”四舍五入是这样的:

Math.Round(2.25, 1, MidpointRounding.AwayFromZero);
这将返回值“2.3”。

关于此行为有这样的说法:

来电者须知

由于可能导致的精度损失 将十进制值表示为浮点数或执行 浮点值的算术运算,在某些情况下 Round(Double,Int32)方法可能无法将中点值四舍五入到 小数位数位置中最近的偶数值。这是 如以下示例所示,其中2.135四舍五入为2.13 而不是2.14。发生这种情况是因为该方法在内部相乘 值乘以10位,本例中的乘法运算 受到精度损失的影响


如果您有一个
十进制
值,它将正确地将
1.275
四舍五入到
1.28

如果您有一个
Double
值,它的行为将不一样,因为值
1.275
无法精确表示。如果使用
double
1.275
,它实际上将略小于确切值
1.275
,类似于
1.2749999999999999


当对该值进行四舍五入时,它不会精确地介于
1.27
1.28
之间,而是稍微接近
1.27
,因此它将向下四舍五入,而不是向上四舍五入。

这是因为四舍五入是一个双精度,而不是小数点:

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

十进制和双精度是非常不同的

根据文档的预期行为

例如,如果小数等于1,则2.15和2.15000都是小数 四舍五入到2.2,因为.05和.05000都在.1和.2之间 .2和.1是奇数。同样,如果小数等于1,则为2.05和 2.05000都四舍五入到2.0,因为.05和.05000都在.0和.1之间,而.0是偶数。这种行为 方法遵循IEEE标准754第4节。这种四舍五入的方法是不正确的 有时称为四舍五入到最近值,或银行家四舍五入。信息技术 最大限度地减少因一致舍入a而导致的舍入误差 单个方向上的中点值。控制 由Round(Decimal,Int32)方法使用的舍入,调用 十进制.舍入(十进制,Int32,中点舍入)重载

从。试一试


很抱歉,尚未找到屏幕截图;-)但我发现了这个博客:你是真的使用了
十进制
值,还是使用了
双精度
?当你说你对
十进制
值进行四舍五入时,有点让人困惑
Math.Round(1.275米,2)=1.28
,而如果使用
double
重载,则在编写时,
Math.Round(1.275米,2)=1.27
。问题很可能是由于浮点表示不准确。如果将1.275四舍五入到1.28,这就是解释,但事实并非如此。
1.275m
1.275
不同。OP要求的是
1.275
。这个“问题”是可以重现的,只是不要把它强加给别人decimal@CodesInChaos我想他指的是“十进制”值,在这个词的“外行”意义上,不是计算机科学意义上的…
1.375
被精确地表示为十进制和双精度。如果该方法返回错误的结果,因为它在内部做了不准确的事情,那么实现是不正确的。更有可能的是,MSDN文档是错误的,Math.Round返回了一个意外的结果,因为调用者没有意识到他们传递的值不是他们所认为的值。例如,在这里提出的问题中,呼叫者传递的不是1.275,而是略小于1.275的值。调用Math.Round之前出错,不在其中。
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
Console.WriteLine(Math.Round(1.275M, 2)); // outputs 1.28
Console.WriteLine(Math.Round(1.375M, 2)); // outputs 1.38
Decimal.Round(a, 2, MidpointRounding.AwayFromZero);