17

[小技巧]你真的了解C#中的Math.Round么?

 4 years ago
source link: http://mp.weixin.qq.com/s?__biz=MzAwNTMxMzg1MA%3D%3D&%3Bmid=2654077165&%3Bidx=6&%3Bsn=1d9badfc2a2c50495982844ff4514e5e
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
mq6rAvv.jpg!web

今天在某.NET Core 群中看到有人在问 Math.Round 的问题。其实这个问题之前有很多人遇到了,在此总结一下。

开发者为了实现小数点后 2 位的四舍五入,编写了如下代码,

var num = Math.Round(12.125, 2);

代码非常的简单,开发者实际得到的结果是 12.12, 这与其所预期的 四舍五入 结果 12.13 相悖。

其实产生这个结果的原因是由于 Math.Round 默认使用的并非是 四舍五入 的原则,而是 四舍六入五成双 的原则。

四舍六入五成双

所谓的 四舍六入五成双 ,就是说当确定有效位数之后,有效位数的下一位如果小于等于 4 就舍去,如果大于等于 6 就进一,当有效位数的下一位是 5 的时候

  • 如果 5 前面为奇数,就舍五进一

  • 如果 5 前面为偶数,就舍五不进(0 是偶数)

从统计学上讲,四舍六入五成双比四舍五入要更精确,因为大量计算的情况下,四舍五入逢五进一,会导致结果偏向大数。

例如:

1.15+1.25+1.35+1.45 = 5.2

如果有效位数是小数点后一位,使用 四舍五入 原则得到的结果

1.2 + 1.3 + 1.4 + 1.5 = 5.4

而使用 四舍六入五成双原则 得到的结果是

1.2 + 1.2 + 1.4 + 1.4 = 5.2

由此可见 四舍六入五成双原则 得到的结果更为精确。

Math.Round 的四舍五入

那么如何使用 Math.Round 实现预期的 四舍五入 呢?

其实 C#中的 Math.Round 提供了非常多的重载方法,其中有两个重载方法是,

public static double Round (double value,
    int digits,
    MidpointRounding mode);
public static decimal Round (decimal d,
    int decimals,
    MidpointRounding mode);

这两个方法都提供了第三个参数 mode , mode 是一个 MidpointRounding 的枚举变量,它有 2 个可选值

  • AwayFromZero - 四舍五入

  • ToEven - 四舍六入五成双

所以如果我们希望得到一个理想中四舍五入的结果,我们可以改用如下代码:

var num = Math.Round(12.125, 2,
    MidpointRounding.AwayFromZero);

b2Q7ryq.jpg!web


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK