我有一个Math.Round的错误,没有任何解释。 我做的时候
Math.Round(81.725, 2, MidpointRounding.AwayFromZero)
结果是81,72,但是当我使用Decimal.Round
时Decimal.Round(81.725M, 2, MidpointRounding.AwayFromZero)
结果是81,73
我明白为什么,你有一个系统地使用Math.Round的解决方案吗?
答案 0 :(得分:3)
在了解Json -> {"abc":"123","def":"456","ghi":"789"}
的工作原理之前,您不应该讨论错误,以及与double
的区别,这些差异可以解释您所看到的行为。
double是具有以下结构的实数的最佳近似值:
decimal
因此,number = sign * mantissa * 2 ^ exponent
表示为81.725,
,实际上是:
double
现在你应该理解为什么1 * 2875442808959795 * 2^-45 = 81,724999999999994315658113919199
解析为Math.Round(81.725, 2)
而不是81.72
。
81.73
不会发生这种情况,因为与decimal
相反,decimal
可以完全代表double
。这是因为81.725
中的缩放因子是decimal
的幂。
这种增加的精度显然是在成本,速度,空间和范围上。何时选择一种类型或另一种类型在评论中提供的另一个SO问题的链接中得到很好的解释。
答案 1 :(得分:0)
下面第二项作业的M
后缀确定数据类型:
Math.Round(81.725, 2, MidpointRounding.AwayFromZero); // double, returns 81.72
Math.Round(81.725M, 2, MidpointRounding.AwayFromZero); // decimal, returns 81.73
Decimal.Round(81.725M, 2, MidpointRounding.AwayFromZero); // decimal, returns 81.73
通过使用该后缀,第二次分配的给定数据类型被视为decimal
而不是double
,使得舍入更精确。
MSDN documentation of Math.Round已经提到了这种差异:
来电者注意事项:
由于代表可能导致精度损失 十进制值作为浮点数或执行算术 对浮点值的操作,在某些情况下为
Round(Double)
方法可能看起来不会将中点值舍入到最近的偶数 整数。强>
Decimal.Round还有进一步的解释:
此方法的行为遵循IEEE标准754第4节 圆形有时被称为圆形<强>一半到均匀或银行家 舍入。它最大限度地减少了始终如一的舍入误差 在单个方向上舍入中点值。它相当于 使用模式调用
Round(Decimal, MidpointRounding)
方法MidpointRounding.ToEven
的论据。
简而言之,decimal
使用IEEE-754,它对中点值使用一致舍入,而double
(和float
)使用没有有限二进制表示的浮点。
其他参考: