Math.Round(8.075, 2, MidpointRounding.AwayFromZero)返回8.07,尽管它应该返回8.08。足够神奇的是,7.075可以正常工作,但是9.075也返回9.07!

该怎么办?没有人知道没有这种错误的舍入方法吗?

最佳答案

如果您像人类一样用10根手指进行计数,那么精确表示十进制值8.075不会有任何麻烦:

  8.075 = 8 x 10^1 + 0 x 10^0 + 7 x 10^-1 + 5 x 10^-2

但是计算机用2根手指来计数,它们需要以2的幂来表示该值:
  8.075 = 1 x 2^3  + 0 x 2^2  + 0 x 2^1  + 0 x 2^0  + 0 x 2^-1 + 0 x 2^-2 + 0 x 2^-3 +
          1 x 2^-4 + 0 x 2^-5 + 0 x 2^-6 + 1 x 2^-7 + 1 x 2^-8 + 0 x 2^-9 + 0 x 2^-10 +
          1 x 2^-11 + ...

我放弃了用手指抽筋键入术语的想法,但要点是,无论您加上2的多少次幂,您都不会得到确切的8.075m。与人类永远无法精确地写出10/3的结果类似的问题,它的小数位数无穷。当您用6根手指数数时,您只能准确地写出该表达式的结果。

处理器当然没有足够的存储空间来存储无限数量的位来表示一个值。因此,他们必须截断数字序列,double类型的值可以存储53位。

因此,十进制值8.075在存储在处理器中时会四舍五入。 53位序列(转换回十进制)为〜8.074999999999999289。然后,按预期将其代码四舍五入为8.07。

如果要获得10个手指的数学结果,则需要使用一种将数字存储在以10为底的数据类型。这是.NET中的System.Decimal类型。使固定:
decimal result = Math.Round(8.075m, 2, MidpointRounding.AwayFromZero)

请注意代码段中的8.075m文字(十进制类型的文字)中字母m的用法。该函数选择用10个手指计数的Math.Round()重载,之前您使用的是使用2手指版本System.Double的重载。

请注意,使用System.Decimal进行计算有一个明显的缺点,那就是 slow 。比使用System.Double(处理器直接支持的值类型)进行计算要慢得多。十进制数学是在软件中完成的,而不是硬件加速的。

关于c# - Math.round错误-怎么办?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/16621832/

10-10 13:00