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.274991.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);