为什么当我执行以下操作时...
Math.Round(0.75, 1, MidpointRounding.AwayFromZero)
我得到0.8
但是当我做以下事情时......
Math.Round(0.575, 2, MidpointRounding.AwayFromZero)
我没有得到0.58。相反,我得到0.57。我想要任何5和更高的东西,所以0.575应该是0.58。
答案 0 :(得分:33)
问题在于你不能将0.575完全表示为二进制浮点数(例如双精度数)。虽然我不确切地知道最接近的表示可能只是稍微低一点,所以在舍入时它使用真实的表示并向下舍入。
如果要避免此问题,请使用更合适的数据类型。 decimal
会做你想做的事:
Math.Round(0.575M, 2, MidpointRounding.AwayFromZero)
结果:0.58
0.75做正确的事情的原因是它很容易用二进制浮点表示,因为它很简单1/2 + 1/4(即2 ^ -1 + 2 ^ -2)。通常,任何有限的2的幂的和可以用二进制浮点表示。例外情况是你的2的功率范围太大(例如2 ^ 100 + 2不能完全代表)。
编辑添加:
Formatting doubles for output in C#可能会对理解为什么它如此难以理解0.575并不是真正的0.575感兴趣。接受的答案中的DoubleConverter将显示0.575作为精确字符串0.5749999999999999555910790149937383830547332763671875
您可以从中看到为什么舍入给出0.57。
答案 1 :(得分:9)
System.Math.Round
方法使用Double
结构,正如其他人所指出的那样,它容易出现浮点精度错误。我遇到它时发现这个问题的简单解决方案 I 是使用System.Decimal.Round
方法,它没有遇到同样的问题,也不需要将变量重新定义为小数:
Decimal.Round(0.575, 2, MidpointRounding.AwayFromZero)
结果:0.58
答案 2 :(得分:2)
这是由于双精度/小数精度不足造成的(即 - 函数不会总是给出你期望的结果)。
请参阅以下链接:MSDN on Math.Round
以下是相关引用:
由于将十进制值表示为浮点数或对浮点值执行算术运算会导致精度损失,因此在某些情况下Round(Double,Int32,MidpointRounding)方法可能看起来不是圆中点模式参数指定的值。这在下面的示例中说明,其中2.135舍入到2.13而不是2.14。这是因为内部方法将值乘以10digits,并且在这种情况下乘法运算会受到精度损失的影响