1

Could someone explain to me why Math.Round(1.565,2) = 1.56 and not 1.57?

Samuel O'Malley
  • 3,471
  • 1
  • 23
  • 41
Pliff
  • 21
  • 1
  • 3

4 Answers4

3

Math.Round() uses the Banker's rounding algorithm. Basically it rounds anything ending in 5 towards the even number. So 1.565 rounds down (towards the 6) but 1.575 rounds up (towards the 8). This avoids the rounding errors from accumulating if you add many rounded numbers.

acfrancis
  • 3,569
  • 25
  • 21
1

The double representation of 1.565 is not exact, and is slightly less than that amount - 1.564999999999999946709294817992486059665679931640625 or thereabouts. So when rounded to only two decimal places, it gets rounded downwards.

Even if you were to use a decimal (which represents decimal fractions exactly) and try Math.round(1.565M,2), this would also get rounded down, as Math.round(number, decimalPlaces) rounds values halfway between one value and the next towards the one whose last digit is even - this is sometimes called banker's rounding. So Math.round(1.575M,2), for example, would round upwards.

pobrelkey
  • 5,853
  • 20
  • 29
  • From the link I posted in the comments I think that this "error" is actually a feature of C# called Banker's Rounding. – Samuel O'Malley Nov 01 '13 at 17:31
  • 1
    @SamuelO'Malley Both come into play in certain situations. If the `double` *is* able to represent the value exactly, then banker's rounding is used. If it *can't*, then it doesn't matter what rounding rules are used; if it's not on the midpoint they don't matter. – Servy Nov 01 '13 at 17:37
  • 1
    @SamuelO'Malley point taken, edited/expanded to add this (and to correct my rusty C# syntax). – pobrelkey Nov 01 '13 at 17:43
1

See: Math.Round Method (Double, Int32)

Because of the loss of precision that can result from representing decimal values as floating-point numbers or performing arithmetic operations on floating-point values, in some cases the Round(Double, Int32) method may not appear to round midpoint values to the nearest even value in the digits decimal position. This is illustrated in the following example, where 2.135 is rounded to 2.13 instead of 2.14. This occurs because internally the method multiplies value by 10digits, and the multiplication operation in this case suffers from a loss of precision.

And the example is:

   public static void Main()
   {
      double[] values = { 2.125, 2.135, 2.145, 3.125, 3.135, 3.145 };
      foreach (double value in values)
         Console.WriteLine("{0} --> {1}", value, Math.Round(value, 2));

   }
Habib
  • 219,104
  • 29
  • 407
  • 436
0

This occurs because internally the method multiplies value by 10digits, and the multiplication operation in this case suffers from a loss of precision. http://msdn.microsoft.com/en-us/library/system.math.round.aspx#Round5_Example and http://msdn.microsoft.com/en-us/library/75ks3aby.aspx

johnny
  • 2,032
  • 1
  • 25
  • 45