简体   繁体   English

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

[英]Math.Round methodology, starting at the smallest decimal

There have been many threads started over the confusion in the way that Math.Round works. Math.Round工作方式中,有很多线程开始出现混乱。 For the most part, those are answered by cluing people in to the MidpointRounding parameter and that most people are expecting MidpointRounding.AwayFromZero . 在大多数情况下,通过将人们引入MidpointRounding参数并且大多数人期待MidpointRounding.AwayFromZero来回答这些问题。 I have a further question though about the actual algorithm implemented by AwayFromZero. 关于AwayFromZero实施的实际算法,我还有一个问题。

Given the following number (the result of a number of calculations): 13.398749999999999999999999999M 给出以下数字(一些计算的结果): 13.398749999999999999999999999M

our users are expecting to see the same result that Excel would give them 13.39875 . 我们的用户希望看到Excel给他们13.39875的相同结果。 As they are currently rounding that number to 4 using Math.Round(num, 4, MidpointRounding.AwayFromZero), the result is off by .0001 from what they expect. 由于他们目前使用Math.Round(num,4,MidpointRounding.AwayFromZero)将该数字四舍五入为4,因此结果与他们期望的结果相差0.0001。 Presumably, the reason for this is that the algorithm just looks at the fifth digit (4), and then rounds accordingly. 据推测,其原因是算法只是查看第五个数字(4),然后相应地进行舍入。 If you were to start rounding at the last 9, the real mathematical answer would in fact give you the same number as excel. 如果你要在最后9开始四舍五入,真正的数学答案实际上会给你与excel相同的数字。

So the question is ... is there a way to emulate this behavior rather than the current? 所以问题是......有没有办法模仿这种行为而不是当前行为?

I've written a recursive function that we could use in the meantime. 我写了一个我们可以在此期间使用的递归函数。 But before we put it in production I wanted to see what SO thought about the problem :-) 但在我们投入生产之前,我想看看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);
    }

Edit: just for clarity, I should have been clearer in my original post. 编辑:为了清楚起见,我应该在原帖中更清楚。 The position of rounding methodology being asked for here is what I'm being presented by the business analysts and users who are reporting the "rounding error". 这里要求舍入方法的位置是我报告“舍入错误”的业务分析师和用户所呈现的内容。 Despite being told numerous times that it's not incorrect, just different than what they are expecting ... this report keeps coming in. So I am just on a data gathering stint to gather as much information as I can on this topic to report back to the users. 尽管多次被告知这不是不正确的,只是与他们期望的不同......这份报告不断涌现。所以我只是在收集数据,尽可能多地收集有关此主题的信息,以便向用户。

In this case, it seems that any other system used to generate these average prices (which we must match) are using a different level precision (10 in the database, and excel seems to default to 15 or something). 在这种情况下,似乎用于生成这些平均价格(我们必须匹配)的任何其他系统使用不同的级别精度(数据库中为10,excel似乎默认为15或其他)。 Given that everyone has a different level of precision, I'm stuck in the middle with the question of moving to a lower precision, some weird rounding rules (as described above), or just having different results than the users expect. 鉴于每个人都有不同的精确度,我陷入中间的问题是移动到较低的精度,一些奇怪的舍入规则(如上所述),或者只是有不同于用户期望的结果。

So if you round that number to 5 places, and then round the result to 4 places... You get a different result than if you just round the original number to 4 places? 因此,如果您将该数字舍入到5个位置,然后将结果舍入到4个位置...您得到的结果与将原始数字四舍五入到4个位置的结果不同? That's expected. 这是预期的。 And I think that explains what you need to do. 而且我认为这解释了你需要做什么。 another option is to have Excel show the full precision so "they" round the same way as your code. 另一种选择是让Excel显示完整的精度,因此“它们”与代码的方式相同。 Rounding twice just seems wrong. 四舍五入似乎是错误的。

If I get you right, people are expecting 13.3988 because they are first rounding to 13.39875 and then to 13.3988 and they need you to be bug-compatible with that. 如果我说得对,人们期待13.3988,因为他们首先进入13.39875然后到13.3988,他们需要你与之相关的错误。

If so, there's no need to repeat any further than one step of rounding, as the flaw in their method only comes in at the last step of rounding (by its nature, rounding removes the significance of the step two steps before it). 如果是这样的话,就没有必要重复进行任何超过一步的舍入,因为他们方法中的缺陷只出现在舍入的最后一步(根据其性质,舍入消除了前两步的重要性)。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM