Dav*_*inn 5 c# excel rounding-error rounding
该值是将 2.01 和 2.52 之和除以 2 的结果(2.01 + 2.52) / 2。Excel 将该值显示为 2.265,当格式化为 2 位数字时,该值为 2.27。但是,文件中存储的值为 2.2649999999999997。当我重新创建这是 C# 时,我也在变量中得到该值,而不是 2.265。据我所知,这是由于 4.53 除以 2 的浮点精度问题造成的。
double result = (2.01 + 2.52) / 2;
Console.WriteLine(result);
Run Code Online (Sandbox Code Playgroud)
控制台显示 2.265,但 QuickWatch 调试器中显示的值显示 2.264999999999997。我怀疑 WriteLine 方法中将值转换为字符串可以纠正浮点精度错误。
当我申请时Math.Round(result, 2, MidpointRounding.AwayFromZero),结果并不2.26像2.27我预期的那样。似乎它查看了我想要四舍五入的数字右侧的第一个数字,发现它是 4,并忽略了它右侧的所有其他数字。问题在于,这些 9 只是由于精度问题而存在,并且需要包含在内,或者更好的是,该值应该是2.265。
我在代码中所做的就是从 Excel 电子表格中读取文本值"2.2649999999999997",将其转换为双精度型2.264999999999999,然后转换为字符串,这给了我"2.265". 然后我将其转换回双精度,2.265以便我可以将 应用于Math.Round它并获得 的预期结果2.27。这是完整的代码:
double result = Convert.ToDouble(((2.01 + 2.52) / 2).ToString());
Console.WriteLine(Math.Round(result, 2, MidpointRounding.AwayFromZero));
Run Code Online (Sandbox Code Playgroud)
我依靠 ToString 来清理浮点精度和舍入问题的方法是否正确?如果不是,我应该怎么做?
第一:这个问题很难。因为 4.53/2 = 2.265。舍入为 2.27。然而,计算中导致较小结果 (2.264999999....) 的最小舍入误差将导致舍入为 2.26。这就是这里正在发生的事情。要解决这个问题,您需要一个浮点算术,它具有与 Excel 相同的内部舍入误差。
从这个文档https://en.wikipedia.org/wiki/Numeric_ precision_in_Microsoft_Excel 看来 Excel 使用IEEE 754 的修改版本,而 C# 使用 IEEE 754。我不知道差异在哪里,但看起来好像在内部Excel 会产生不同的舍入误差。
本文档介绍了这些差异:https://support.microsoft.com/en-us/kb/78113/en-us (例如,Excel 不使用非规范化数字。这意味着对于小于 2 的数字的舍入误差有不同的行为)。
所以我假设你不能使用“double”来解决这个问题
更新
然而,现在我明白问题不在于算术,而在于Excel显示数字的方式,也许这是一个解决方案
Math.Round(Math.Round(result, 3, MidpointRounding.AwayFromZero), 2, MidpointRounding.AwayFromZero)
Run Code Online (Sandbox Code Playgroud)
首先四舍五入到 3 位,然后四舍五入到 2 位。在我看来,Excel 就是这样做的。