Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Math.Round methodology, starting at the smallest decimal

Tags:

c#

math

rounding

There have been many threads started over the confusion in the way that Math.Round works. For the most part, those are answered by cluing people in to the MidpointRounding parameter and that most people are expecting MidpointRounding.AwayFromZero. I have a further question though about the actual algorithm implemented by AwayFromZero.

Given the following number (the result of a number of calculations): 13.398749999999999999999999999M

our users are expecting to see the same result that Excel would give them 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. Presumably, the reason for this is that the algorithm just looks at the fifth digit (4), and then rounds accordingly. If you were to start rounding at the last 9, the real mathematical answer would in fact give you the same number as 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 :-)

    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). 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.

like image 293
Joel Martinez Avatar asked Aug 27 '10 13:08

Joel Martinez


People also ask

How do you round to the least decimal places?

To round a number to the nearest tenth , look at the next place value to the right (the hundredths). If it's 4 or less, just remove all the digits to the right. If it's 5 or greater, add 1 to the digit in the tenths place, and then remove all the digits to the right.

Can 0.5 be rounded?

0.5 rounded off to the nearest whole number is 1. Since, the value after decimal is equal to 5, then the number is rounded up to the next whole number. Hence, the whole number of 0.5 will be 1.

What does it mean to round to the first decimal place?

When you round to the first decimal place, or to the nearest tenth, the number in the hundredth point place will determine whether you round up or down. If the hundredths digit is a number between 5 and 9, round up to the nearest whole number.

What is rounding by the .5 rule?

In rounding off numbers, if the first figure dropped is 5, and all the figures following the five are zero or if there are no figures after the 5, then the last figure kept should be unchanged if that last figure is even. For example, if only one decimal is to be kept, then 6.6500 becomes 6.6.


2 Answers

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.

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);
}
like image 173
Jon Hanna Avatar answered Nov 29 '22 10:11

Jon Hanna


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? 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. Rounding twice just seems wrong.

like image 40
phkahler Avatar answered Nov 29 '22 10:11

phkahler