Math.Round方法,从最小的小数开始四舍五入。

7
有很多帖子讨论了 Math.Round 的工作方式存在的混淆。大多数情况下,这些问题都可以通过向人们提示 MidpointRounding 参数并且大多数人都期望 MidpointRounding.AwayFromZero 来解决。但是我对 AwayFromZero 实际实现的算法有进一步的问题。
给定以下数字(许多计算的结果):13.398749999999999999999999999M 我们的用户期望看到与 Excel 相同的结果 13.39875。由于他们目前使用 Math.Round(num,4,MidpointRounding.AwayFromZero)将该数字四舍五入,因此结果与他们期望的差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或其他)。鉴于每个人都有不同的精度水平,我陷入了困境,需要考虑降低精度、采用一些奇怪的舍入规则(如上所述),或者只是得到与用户期望不同的结果。


1
我不同意“实际的数学答案与Excel给出的数字相同”这个说法。数学舍入是明确定义的,并且不是从最低有效数字开始。将13.39874999舍入到6个有效数字,数学上的结果确实是13.3987。 - Stephen Cleary
1
@Stephen,如果我理解他的意思正确的话,他想要进行真正的数学运算,得到与有缺陷的方法相同的结果,以便具备兼容错误的 bug 特性。 - Jon Hanna
@Jon:同意。我只是想纠正双重舍入在数学上是正确的,因此是预期行为的印象。 - Stephen Cleary
@Stephen,没错。即使不使用小学四舍五入(由AwayFromZero提供),解释其他选择也不是错误的,这已经很困难了,更不要说让它变得更模糊了。我认为提问者已经明白了这一点,但我们应该始终考虑通过谷歌搜索进来的人。 - Jon Hanna
@Joel Martinez:我不确定你在问什么。你的Excel示例是到5位小数,那么为什么你的用户希望得到4位小数的相同答案呢? - Rick Regan
显示剩余3条评论
2个回答

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);
}

双重舍入并非最终结果。对于任意次数的重复,都有相应的示例。 例如,只有在从右到左每个位置上连续应用10次向远离零的舍入时,0.4444444449才会四舍五入为1。 - jmster

3

所以,如果你将那个数字舍入到5位,然后将结果舍入到4位……与仅将原始数字舍入到4位相比,你会得到不同的结果?这是可以预料的。我认为这解释了你需要做什么。另一个选项是让Excel显示完整精度,这样"他们"就能像你的代码一样进行舍入。两次舍入似乎是错误的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接