c# - Math.Round方法,从最小的小数点开始

Math.Round的工作方式上,有很多线程开始解决困惑问题。在大多数情况下,可以通过将人们吸引到MidpointRounding参数来回答这些问题,并且大多数人都期待MidpointRounding.AwayFromZero。我对AwayFromZero实现的实际算法还有一个疑问。

给定以下数字(许多计算的结果):13.398749999999999999999999999M
我们的用户期望看到与Excel给他们13.39875相同的结果。由于他们当前使用Math.Round(num,4,MidpointRounding.AwayFromZero)将数字四舍五入,因此结果与他们的期望值相差.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左右)。考虑到每个人的精度水平都不同,我陷入了一个中间问题,那就是降低精度,一些奇怪的舍入规则(如上所述),或者结果与用户期望的不同。

最佳答案

如果我说对了,人们期望的是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);
}