Search code examples
c#roundingbankers-rounding

C# banker's rounding error


double a = 18.565
return Math.Round(a,2)

..returns 18.57.
For every other number I tried banker's rounding worked as expected, for example Math.Round(2.565,2) returned 2.56.

Any clue why and when that happens? Is it error or am I missing something about banker's rounding?

Thanks..


Solution

  • As Matthew said, 18.565 can't be accurately represented. The actual value used is 18.565000000000001278976924368180334568023681640625 (found using DoubleConverter), which is clearly beyond half-way. Now I've a sneaking feeling that sometimes Math.Round will consider a value which is actually beyond the half-way point, but which is as close to the half-way point as can be accurately represented, as being exactly at that point. However, I haven't seen any documentation describing the situations in which that's applied, and clearly it's not happening in this case. I wouldn't want to rely on it.

    Even the rounded value isn't exactly 18.57 of course. It's actually 18.57000000000000028421709430404007434844970703125.

    Fundamentally, if you really, really care about representing decimal values accurately, you should be using decimal. That's not just in terms of Math.Round - it goes to every aspect of handling floating point values.

    That does give the right value for Math.Round, of course:

    decimal m = 18.565m;
    Console.WriteLine(Math.Round(m, 2)); // Prints 18.56