试图模仿Excel舍入让我感到悲伤

时间:2015-07-07 20:48:10

标签: 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);

控制台显示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,然后转换为字符串,这样就可以{{1} }。然后我将其转换回双"2.265",以便我可以将2.265应用于它并获得Math.Round的预期结果。这是完整的代码:

2.27

我的方法是浮点精度和舍入问题,依靠ToString来清理它,正确的吗?如果没有,我该怎么做?

1 个答案:

答案 0 :(得分:0)

第一:问题很难。因为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)

第一轮到第3轮,然后是2位数。在我看来,Excel正在这样做。