首页 新闻 会员 周边 捐助

.NET Math.Round問題

0
悬赏园豆:50 [已解决问题] 解决于 2012-12-12 09:17

在使用Math.Round的過程中發現可以指定是用一般的四捨五入,和banker's rounding

MidpointRounding.ToEven. If the digit in the decimals position is odd, it is changed to an even digit. Otherwise, it is left unchanged. This behavior follows IEEE Standard 754, section 4. It 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.

AwayFromZero. The digit in the decimals position is always rounded up to the next digit. This is the most commonly known rounding method. It is known as symmetric arithmetic rounding.

可是我發現如下例子得到結果並非預期
banker's rounding
四舍六入五考虑,五后非零就进一,五后皆零看奇偶,五前为偶应舍
去,五前为奇要进一
Console.WriteLine(Math.Round(1.225,2,MidpointRounding.ToEven));
預期:1.22 實際 1.23
  
一般四舍六入五
Console.WriteLine(Math.Round(1.265,2,MidpointRounding.AwayFromZero));
預期:1.27 實際 1.26

請問有知道原因的嗎?

MingQ的主页 MingQ | 菜鸟二级 | 园豆:312
提问于:2012-12-11 11:27
< >
分享
最佳答案
0

你使用的是这个重载:

//Math.cs
public static double Round(double value, int digits, MidpointRounding mode)

而正确的应当是这个:

//Math.cs
public static decimal Round(decimal d, int decimals, MidpointRounding mode)

正如楼上所说,加一个m就对了。这是解决方法。

为什么会出现这个问题 

这是由于计算机无法非常准确地表示1.225d这个数,它实际上是被存储为1.2249999999……,1.265d是同样的道理。1.235d就不存在这个问题(因为它恰好能够准确表示,能不能准确存储取决于它的2进制值)。这并非是C#独有的,几乎所有的编程语言都会这样,并且这并非是“预料之外”的,实际上它是国际标准,更详细的C#中浮点数讲解看这里。所以在有关业务数据的计算中,都应当使用decimal数据类型。

收获园豆:30
水牛刀刀 | 大侠五级 |园豆:6350 | 2012-12-11 12:42
其他回答(1)
0

Console.WriteLine(Math.Round(1.225M,2,MidpointRounding.ToEven));

收获园豆:20
Launcher | 园豆:45050 (高人七级) | 2012-12-11 11:37

能否説明一下其中的緣由?

支持(0) 反对(0) MingQ | 园豆:312 (菜鸟二级) | 2012-12-11 12:57

@MingQ: 1.225M 表示是 decimal 类型,1.225 表示是 double 类型,decimal 精度比 double 高,可以完整的表示 0.005,而 double 不行,实际会被表示为 0.00499999999.....。这样你在 Round 的时候,第三位就不是 5,而是 4 了。

支持(0) 反对(0) Launcher | 园豆:45050 (高人七级) | 2012-12-11 13:07

@Launcher: 学习了

支持(0) 反对(0) 茂茂 | 园豆:2898 (老鸟四级) | 2012-12-11 14:05
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册