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

Joe*_*nez 7 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);
    }
Run Code Online (Sandbox Code Playgroud)

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

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

Jon*_*nna 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);
}
Run Code Online (Sandbox Code Playgroud)