Why does Math.Round(2.5) return 2 instead of 3?

.net, rounding

Solution

Firstly, this wouldn't be a C# bug anyway - it would be a .NET bug. C# is the language - it doesn't decide how `Math.Round` is implemented.

And secondly, no - if you read the docs, you'll see that the default rounding is "round to even" (banker's rounding):

Return Value Type: System.Double The integer nearest a. If the fractional component of a is halfway between two integers, one of which is even and the other odd, then the even number is returned. Note that this method returns a `Double` instead of an integral type.

Remarks The behavior of this method follows IEEE Standard 754, section 4. This kind of rounding is sometimes called rounding to nearest, or banker's rounding. It minimizes rounding errors that result from consistently rounding a midpoint value in a single direction.

You can specify how `Math.Round` should round mid-points using an overload which takes a `MidpointRounding` value. There's one overload with a `MidpointRounding` corresponding to each of the overloads which doesn't have one:

- `Round(Decimal)` / `Round(Decimal, MidpointRounding)`

- `Round(Double)` / `Round(Double, MidpointRounding)`

- `Round(Decimal, Int32)` / `Round(Decimal, Int32, MidpointRounding)`

- `Round(Double, Int32)` / `Round(Double, Int32, MidpointRounding)`

Whether this default was well chosen or not is a different matter. (`MidpointRounding` was only introduced in .NET 2.0. Before then I'm not sure there was any easy way of implementing the desired behaviour without doing it yourself.) In particular, history has shown that it's not the expected behaviour - and in most cases that's a cardinal sin in API design. I can see why Banker's Rounding is useful... but it's still a surprise to many.

You may be interested to take a look at the nearest Java equivalent enum (`RoundingMode`) which offers even more options. (It doesn't just deal with midpoints.)

Problem

In C#, the result of `Math.Round(2.5)` is 2. It is supposed to be 3, isn't it? Why is it 2 instead in C#?

Original source

Related problems