在c#中,Math.Round(2.5)的结果是2。
应该是3,不是吗?为什么在c#中它是2 ?
在c#中,Math.Round(2.5)的结果是2。
应该是3,不是吗?为什么在c#中它是2 ?
当前回答
这是非常丑陋的,但总是产生正确的算术四舍五入。
public double ArithRound(double number,int places){
string numberFormat = "###.";
numberFormat = numberFormat.PadRight(numberFormat.Length + places, '#');
return double.Parse(number.ToString(numberFormat));
}
其他回答
首先,无论如何这都不是c#错误——而是。net错误。c#是一种语言——它不决定数学如何。实现了Round。
其次,不,如果你读了文档,你会发现默认的舍入是“舍入到偶数”(银行家的舍入):
Return ValueType: System.DoubleThe integer nearest a. If the fractional component of a is halfway between two integers, one of which is even and the other odd, then the even number is returned. Note that this method returns a Double instead of an integral type. RemarksThe behavior of this method follows IEEE Standard 754, section 4. This kind of rounding is sometimes called rounding to nearest, or banker's rounding. It minimizes rounding errors that result from consistently rounding a midpoint value in a single direction.
你可以指定Math。Round应该使用重载对中点进行四舍五入,重载取midpointrsurround值。这里有一个带有midpointround的重载,对应于每个没有midpointround的重载:
圆(Decimal,中角) 圆(双)/圆(双,中点) 圆(Decimal, Int32) /圆(Decimal, Int32,中角肌) 圆(Double, Int32) /圆(Double, Int32,中角)
这种默认选择是否得当则是另一回事。(midpointround只是在。net 2.0中引入的。在此之前,我不确定是否有任何简单的方法来实现所需的行为,而不是自己动手。)特别是,历史已经表明,这不是预期的行为——在大多数情况下,这是API设计中的大忌。我知道为什么银行家舍入是有用的…但这对许多人来说仍然是一个惊喜。
您可能有兴趣看看最近的Java等效枚举(RoundingMode),它提供了更多的选项。(它不只是处理中点。)
因为Silverlight不支持midpointrsurround选项,所以你必须自己编写。喜欢的东西:
public double RoundCorrect(double d, int decimals)
{
double multiplier = Math.Pow(10, decimals);
if (d < 0)
multiplier *= -1;
return Math.Floor((d * multiplier) + 0.5) / multiplier;
}
关于如何使用它作为扩展的例子,请参阅文章:.NET和Silverlight圆整
这是非常丑陋的,但总是产生正确的算术四舍五入。
public double ArithRound(double number,int places){
string numberFormat = "###.";
numberFormat = numberFormat.PadRight(numberFormat.Length + places, '#');
return double.Parse(number.ToString(numberFormat));
}
这被称为舍入到偶数(或银行家舍入),这是一种有效的舍入策略,可以最大限度地减少总和中的累积错误(MidpointRounding.ToEven)。理论是,如果你总是在同一个方向四舍五入一个0.5的数字,误差会更快地累积(四舍五入到偶数应该是最小化)(a)。
以下是MSDN对以下内容的描述:
Math.Floor, which rounds down towards negative infinity. Math.Ceiling, which rounds up towards positive infinity. Math.Truncate, which rounds up or down towards zero. Math.Round, which rounds to the nearest integer or specified number of decimal places. You can specify the behavior if it's exactly equidistant between two possibilities, such as rounding so that the final digit is even ("Round(2.5,MidpointRounding.ToEven)" becoming 2) or so that it's further away from zero ("Round(2.5,MidpointRounding.AwayFromZero)" becoming 3).
下面的图表可能会有所帮助:
-3 -2 -1 0 1 2 3
+--|------+---------+----|----+--|------+----|----+-------|-+
a b c d e
a=-2.7 b=-0.5 c=0.3 d=1.5 e=2.8
====== ====== ===== ===== =====
Floor -3 -1 0 1 2
Ceiling -2 0 1 2 3
Truncate -2 0 0 1 2
Round(ToEven) -3 0 0 2 3
Round(AwayFromZero) -3 -1 0 2 3
请注意,Round比它看起来强大得多,因为它可以舍入到特定的小数点后数位。其他的都是0小数。例如:
n = 3.145;
a = System.Math.Round (n, 2, MidpointRounding.ToEven); // 3.14
b = System.Math.Round (n, 2, MidpointRounding.AwayFromZero); // 3.15
对于其他函数,你必须使用乘除技巧来达到相同的效果:
c = System.Math.Truncate (n * 100) / 100; // 3.14
d = System.Math.Ceiling (n * 100) / 100; // 3.15
(a)当然,这个理论取决于这样一个事实,即你的数据在偶数一半(0.5,2.5,4.5,…)和奇数一半(1.5,3.5,…)之间的值分布相当均匀。
如果所有的“半值”都是偶数(例如),错误就会像你总是四舍五入一样快速累积。
从MSDN:
默认为Math。圆的使用 MidpointRounding.ToEven。大多数人 不熟悉“四舍五入? 甚至“作为替代”,四舍五入 “远离零”更常见 . net默认为 “四舍五入到偶数” 统计上的优势是因为 没有分享的倾向 四舍五入的意思是四舍五入 比它循环的频率稍高 向下(假设数字为 四舍五入往往是积极的。)
http://msdn.microsoft.com/en-us/library/system.math.round.aspx