-2

I must be missing some subtlety of .NET rounding. So I am looking at this example:

decimal num = 2.5M;
var result = Math.Round(num);

Why is result = 2? (I would have expected 3 since it should round up)

Denis
  • 11,796
  • 16
  • 88
  • 150

2 Answers2

7

See MSDN:

Decimal Math.Round(Decimald)

Rounds a decimal value to the nearest integer, and rounds midpoint values to the nearest even number (example).

"Midpoint" here means .5; the even number in your case is 2. If you rounded 3.5 this way, it would result in 4.

If you want to use "away from zero" rounding instead, you can use the System.MidpointRounding.AwayFromZero enum:

decimal d = 2.5M;
decimal roundedD = Math.Round(d, MidpointRounding.AwayFromZero); // results in 3

Regarding why it uses midpoint rounding (AKA "banker's rounding") by default instead of "away from zero" rounding, see this answer. Supposedly it's a better algorithm (i.e. more efficient over many iterations).

Community
  • 1
  • 1
rory.ap
  • 34,009
  • 10
  • 83
  • 174
  • 2
    Why would they do it this way? This sounds counter to how rounding has been taught to me all these years. – Denis Oct 17 '16 at 20:17
  • so 4.5 would round to 4? – Denis Oct 17 '16 at 20:17
  • 3
    @Denis This is known as "banker's rounding". .5 is exactly in between the two whole numbers, so to always round up would bias your results higher than reality. – GalacticCowboy Oct 17 '16 at 20:18
  • They did it so that statistically the total will be closer to the precise total. Imagine you do a sum of 100 rounded values. if about half of them are rounded up and half down, you will get a more correct total than if they all rounded up. My personal opinion - even though I understand this, I disagree with this, I think they should have used the standard rules. – bib1257 Oct 17 '16 at 20:21
  • never knew about "banker's rounding". Was just doing something simple and never thought the rabbit hole ran this deep. – Denis Oct 17 '16 at 20:21
  • It is called banker's rounding, it is the default rounding in IEEE 754 computing functions. It is designed this way so that the the average value of the rounded numbers is the same as that of the original numbers. For example round(2.5)+round(3.5)=6 instead of 7. – Alex Oct 17 '16 at 20:22
  • 1
    @Denis -- I stumbled across the very same thing a number of years back, and I was just as surprised. – rory.ap Oct 17 '16 at 20:26
  • 2
    @bib1257 *"I think they should have used the standard rules"*, if you are working in finance, that is the standard rules. That is why it is called ***Bankers*** rounding. – Scott Chamberlain Oct 17 '16 at 21:08
5

If you want classic rounding use

        decimal num = 2.5M;
        var result = Math.Round(num,0, MidpointRounding.AwayFromZero);

Please see https://msdn.microsoft.com/en-us/library/system.math.round(v=vs.110).aspx for details

Scott Chamberlain
  • 124,994
  • 33
  • 282
  • 431
bib1257
  • 325
  • 2
  • 7