需要帮助舍入到小数点后两位

Ste*_*e B 20 .net vb.net math-functions

为什么当我做以下事情时......

Math.Round(0.75, 1, MidpointRounding.AwayFromZero)
Run Code Online (Sandbox Code Playgroud)

我得到0.8

但是当我做以下事情时......

Math.Round(0.575, 2, MidpointRounding.AwayFromZero)
Run Code Online (Sandbox Code Playgroud)

我不懂0.58.相反,我得到0.57.我想要任何5和更高的东西,所以0.575应该是0.58.

Chr*_*ris 34

问题是你不能将0.575完全表示为二进制浮点数(例如双精度).虽然我不确切地知道最接近的表示可能只是稍微低一点,因此在舍入时使用真实表示并向下舍入.

如果要避免此问题,请使用更合适的数据类型.decimal会做你想做的事:

Math.Round(0.575M, 2, MidpointRounding.AwayFromZero)
Run Code Online (Sandbox Code Playgroud)

结果: 0.58

0.75做正确的事情的原因是它很容易用二进制浮点表示,因为它是简单的1/2 + 1/4(即2 ^ -1 + 2 ^ -2).通常,任何有限的2的幂的和可以用二进制浮点表示.例外情况是当你的2的幂超过一个范围时(例如2 ^ 100 + 2不能完全表示).

编辑添加:

在理解为什么它很难理解0.575不是真正的0.575时,格式化C#输出的双精度可能是有意义的.接受的答案中的DoubleConverter将显示0.575作为精确字符串0.5749999999999999555910790149937383830547332763671875您可以从中看到为什么舍入给出0.57.

  • 感谢所有信息人员.我将双倍切换为小数,这就是诀窍.谢谢! (2认同)

Ant*_*ony 9

System.Math.Round方法使用该Double结构,正如其他人所指出的那样,该结构易于出现浮点精度误差.简单的解决办法发现这个问题时,我遇到的是使用System.Decimal.Round方法,它不会有同样的问题,并不需要redifining您的变量小数:

Decimal.Round(0.575, 2, MidpointRounding.AwayFromZero)
Run Code Online (Sandbox Code Playgroud)

结果:0.58