Math.Round方法,从最小的十进制开始

时间:2010-08-27 13:19:39

标签: c# math rounding

Math.Round的工作方式已经引发了很多线索。在大多数情况下,通过将人们引入MidpointRounding参数并且大多数人期待MidpointRounding.AwayFromZero来回答这些问题。关于AwayFromZero实施的实际算法,我还有一个问题。

给出以下数字(大量计算的结果):13.398749999999999999999999999M

我们的用户希望看到Excel为他们13.39875提供的结果相同。由于他们目前使用Math.Round(num,4,MidpointRounding.AwayFromZero)将该数字四舍五入为4,因此结果与他们期望的结果相差0.0001。据推测,其原因是算法只是查看第五个数字(4),然后相应地进行舍入。如果你要在最后9开始四舍五入,真正的数学答案实际上会给你与excel相同的数字。

所以问题是......有没有办法模仿这种行为而不是当前的行为?

我已经编写了一个我们可以同时使用的递归函数。但在我们投入生产之前,我想看看SO对这个问题的看法: - )

    private decimal Round(decimal num, int precision)
    {
        return Round(num, precision, 28);
    }

    private decimal Round(decimal num, int precision, int fullPrecision)
    {
        if (precision >= fullPrecision) return Math.Round(num, precision);

        return Round(Math.Round(num, fullPrecision), precision, --fullPrecision);
    }

编辑:为了清楚起见,我应该在原帖中更清楚。这里要求舍入方法的位置是我报告“舍入错误”的业务分析师和用户所呈现的内容。尽管多次被告知这不是不正确的,只是与他们期望的不同......这份报告不断涌现。所以我只是在收集数据,尽可能多地收集有关此主题的信息,以便向用户。

在这种情况下,似乎用于生成这些平均价格(我们必须匹配)的任何其他系统使用不同的级别精度(数据库中为10,excel似乎默认为15或其他) 。鉴于每个人都有不同的精确度,我陷入了中间的问题,即移动到较低的精度,一些奇怪的舍入规则(如上所述),或者只是有不同于用户期望的结果。

2 个答案:

答案 0 :(得分:3)

因此,如果你将这个数字四舍五入到5个位置,然后将结果四舍五入到...那么你得到的结果与你将原始数字四舍五入到4个位置的结果不同?这是预期的。而且我认为这解释了你需要做什么。另一种选择是让Excel显示完整的精度,因此“它们”与代码的方式相同。四舍五入似乎是错误的。

答案 1 :(得分:3)

如果我说得对,人们期待13.3988,因为他们首先是13.39875然后是13.3988,他们需要你与之相关的错误。

如果是这样的话,没有必要重复进行任何超过一步的舍入,因为他们方法中的缺陷只出现在舍入的最后一步(根据其性质,舍入去除了前两步的重要性。 )。

private static decimal InaccurateRound(decimal num, int precision)
{
  return Math.Round(
    Math.Round(num, precision + 1, MidpointRounding.AwayFromZero),
    precision, MidpointRounding.AwayFromZero);
}