.net 需要帮助四舍五入到小数点后2位吗

.net 需要帮助四舍五入到小数点后2位吗,.net,vb.net,math-functions,.net,Vb.net,Math Functions,为什么当我做以下事情时 Math.Round(0.75, 1, MidpointRounding.AwayFromZero) Math.Round(0.575, 2, MidpointRounding.AwayFromZero) 我得到0.8分 但是当我做以下事情的时候 Math.Round(0.75, 1, MidpointRounding.AwayFromZero) Math.Round(0.575, 2, MidpointRounding.AwayFromZero) 我得不到0.5

为什么当我做以下事情时

Math.Round(0.75, 1, MidpointRounding.AwayFromZero)
Math.Round(0.575, 2, MidpointRounding.AwayFromZero)
我得到0.8分

但是当我做以下事情的时候

Math.Round(0.75, 1, MidpointRounding.AwayFromZero)
Math.Round(0.575, 2, MidpointRounding.AwayFromZero)

我得不到0.58分。相反,我得到了0.57。我想要的是5和5以上的四舍五入,所以0.575应该是0.58。

问题是你不能将0.575精确地表示为二进制浮点数(例如双精度)。虽然我不知道确切的情况,但看起来最接近的表示法可能只是稍微低一点,所以当四舍五入时,它使用真实的表示法并向下四舍五入

如果要避免此问题,请使用更合适的数据类型<代码>十进制将执行您想要的操作:

Math.Round(0.575M, 2, MidpointRounding.AwayFromZero)
结果:
0.58

0.75之所以正确,是因为它很容易用二进制浮点表示,因为它是简单的1/2+1/4(即2^-1+2^-2)。一般来说,任何二次幂的有限和都可以用二进制浮点表示。例外情况是当你的2的幂跨越了太大的范围(例如2^100+2不是完全可以表示的)

编辑以添加:


可能有兴趣理解为什么0.575不是真正的0.575这么难理解。接受答案中的DoubleConverter将显示0.575作为精确字符串是
0.5749999999999555910790149993738305432732763671875
您可以从中看出为什么舍入为0.57。

这是由于双精度/小数精度不足造成的(即-函数不会总是给出您期望的结果)

请参阅以下链接:

以下是相关报价:

由于将十进制值表示为浮点数或对浮点数执行算术运算可能会导致精度损失,因此在某些情况下,舍入(Double、Int32、中点舍入)方法可能不会按照模式参数的指定对中点值进行四舍五入。下面的示例说明了这一点,其中2.135被四舍五入为2.13,而不是2.14。出现这种情况的原因是,该方法在内部将值乘以10位,并且在这种情况下,乘法运算会损失精度


System.Math.Round
方法使用了
Double
结构,正如其他人所指出的,这种结构容易出现浮点精度错误。当我遇到这个问题时,我找到了一个简单的解决方案,就是使用
System.Decimal.Round
方法,它不会遇到同样的问题,也不需要将变量重新定义为小数:

Decimal.Round(0.575, 2, MidpointRounding.AwayFromZero)

结果:0.58

应该有助于回答这个问题。@KenWhite:我不确定它是否会。问题是,通过真正的数学运算,将
.575
四舍五入到离零两位小数,将得到
.58
,但这不是观察到的结果。在这种情况下,这与浮点表示有关。@Chris:你说得对。:-)我主要使用Delphi,它的Round()在大多数情况下都可以处理类似的事情。不过,我刚在C#登记,可以看到这个问题。谢谢所有的信息。我把我的双精度转换成十进制,这就成功了。谢谢