c# – Math.round bug – 该怎么办?

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.075米.类似的问题是人类如何不能精确地写出10/3的结果,它在分数中具有无限数量的数字.只有6个手指计数时,才能准确地写出该表达式的结果.

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

结果,当十进制值8.075存储在处理器中时,它将被舍入.转换回十进制的53位序列是值~8.074999999999999289.然后,正如预期的那样,您的代码将四舍五入到8.07.

如果你想要10个手指数学结果,你需要使用一个数据类型来存储基数为10.这就是.NET中的System.Decimal类型.固定:

decimal result = Math.Round(8.075m,MidpointRounding.AwayFromZero)

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

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

相关文章

在项目中使用SharpZipLib压缩文件夹的时候,遇到如果目录较深,则压缩包中的文件夹同样比较深的问题。比...
项目需要,几十万张照片需要计算出每个照片的特征值(调用C++编写的DLL)。 业务流程:选择照片...
var array = new byte[4]; var i = Encoding.UTF8.GetBytes(100.ToString("x2"));//...
其实很简单,因为Combox的Item是一个K/V的object,那么就可以把它的items转换成IEnumerable<Dic...
把.net4.6安装包打包进安装程序。 关键脚本如下: 头部引用字符串对比库 !include "WordFunc....
项目需求(Winform)可以批量打印某个模板,经过百度和摸索,使用iTextSharp+ZXing.NetʿreeSp...