Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Math.Round() yields unexpected result for double

Tags:

c#

.net

double

I stumbled across a method in my code where a rounded value is calculated wrong in my code. I am aware about the problem with comparing double values generated unexpected results.

Example

    double x = 19.08;
    double y = 2.01;
    double result = 21.09;

    if (x + y == result)
    {
        // this is never reached
    }

Explanation here: http://csharpindepth.com/Articles/General/FloatingPoint.aspx

However, until now, I expected the Math.Round() method to be accurate even with double values.

Look at this code.

        var decimals = 2;
        var value1 = 4.725;
        var value2 = 4.725M;

        var result1 = Math.Round(value1, decimals, MidpointRounding.ToEven);
        var result2 = Math.Round(value1, decimals, MidpointRounding.AwayFromZero);
        var result3 = Math.Round(value2, decimals, MidpointRounding.ToEven);
        var result4 = Math.Round(value2, decimals, MidpointRounding.AwayFromZero);

        Console.WriteLine("Double (ToEven): {0}", result1); // outputs 4.72
        Console.WriteLine("Double (AwayFromZero): {0}", result2); // outputs 4.72 (expected: 4.73)
        Console.WriteLine("Decimal (ToEven): {0}", result3); // outputs 4.72
        Console.WriteLine("Decimal (AwayFromZero): {0}", result4); // outputs 4.73

For me, it is totally clear that result2 should be 4.73. However, it is not the case. Can someone explain why?

like image 811
Jürgen Steinblock Avatar asked Aug 28 '12 11:08

Jürgen Steinblock


People also ask

Which of these function should I use to round 2.5 to 2?

The FLOOR function in Excel is used to round a given number down, to the nearest multiple of a specified significance. Number - the number you want to round. Significance - the multiple to which you wish to round the number. For example, =FLOOR(2.5, 2) rounds 2.5 down to the nearest multiple of 2, which is 2.

How do you round a double in C#?

Round(Double, Int32, MidpointRounding) This method is used to rounds a double precision floating-point value to a specified number of fractional digits. A parameter specifies how to round the value if it is midway between two numbers.

Does Math round round up or down?

If the number you are rounding is followed by 5, 6, 7, 8, or 9, round the number up. Example: 38 rounded to the nearest ten is 40. If the number you are rounding is followed by 0, 1, 2, 3, or 4, round the number down. Example: 33 rounded to the nearest ten is 30.

How do I round a number in VB net?

Round With no options, we use just one argument. This rounds the number to 123. And With a second argument of 1, we round to one decimal place. This yields the values 123.5 (for AwayFromZero) and 123.4 (for ToEven).


2 Answers

Well, you may want to rethink your notion of »totally clear« because 4.725 (as opposed to 4.625) cannot be represented exactly with a double. It's actually exactly

4.7249999999999996447286321199499070644378662109375

Keep in mind that floating-point numbers are just an approximation to the mathematical concept of real numbers – many of your intuitive notions about how numbers should behave don't apply. You end up with a value that is approximately 4.725 but obviously just slightly below it. The midpoint rounding mode will therefore do nothing here as it's not exactly halfway between two possible numbers to round.

like image 107
Joey Avatar answered Oct 20 '22 16:10

Joey


Your value1 could easily be 4.724999999999999999999999999999999. Why should it be rounded to to 4.73 instead of 4.72?

like image 1
Serg Rogovtsev Avatar answered Oct 20 '22 15:10

Serg Rogovtsev