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#?
Both 1.5 and 2.5 are rounded to 2 . 3.5 and 4.5 are rounded to 4 . It prevents cumulative rounding errors and this is why it's often used in science (we use it as a default mode in our sig fig calculator.
Since, 2.5 being the decimal number, it is not considered to be a whole number. However, it can be converted to a whole number by rounding it off to the nearest whole number. 2.5 rounded off to the nearest whole number is 3. Hence, the whole number of 2.5 will be 3.
The round() function rounding strategy and return type have changed. Exact halfway cases are now rounded to the nearest even result instead of away from zero. (For example, round(2.5) now returns 2 rather than 3.)
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.
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 aDouble
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.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With