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或其他) 。鉴于每个人都有不同的精确度,我陷入了中间的问题,即移动到较低的精度,一些奇怪的舍入规则(如上所述),或者只是有不同于用户期望的结果。
答案 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);
}