24

The following applies:

var rounded = Decimal.Round(7.635m, 2);
//rounded: 7.63

This, to me, is wrong and unexpected behavior. I would assume the value of rounded to be 7.64.

To achieve this, I can do:

var rounded = Decimal.Round(7.635m, 2, MidpointRounding.AwayFromZero);
//rounded: 7.64

How can this not be the default behavior of Decimal.Round? Any good reason for this?

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
Erik Kinding
  • 1,742
  • 2
  • 15
  • 32
  • Take a look at http://stackoverflow.com/a/977807/525138, I don't think you can change the default. – Dutts Mar 14 '13 at 09:40
  • 3
    I suppose they chose this as the default because most rounding on Decimals is done on currency. Unfortunately, it's also the default for double.Round(), which really royally stuffs a lot of mathematical calculations - especially ones to do with calculating pixel coordinates. – Matthew Watson Mar 14 '13 at 09:59
  • 3
    Does anybody notice that the default round-to-even **is rounding to odd in your example**?!! I have found this (mis?)behavior on one machine but not on another. Does anody know what's going on? – Timo May 27 '16 at 09:07
  • weird because in .NET Core `decimal.Round(7.635m, 2);` gives `7.64` – Konrad Sep 11 '18 at 13:32

3 Answers3

22

How can this not be the default behavior of Decimal.Round? Any good reason for this?

If you look at the documentation of Decimal.Round Method (Decimal)

The behavior of this method follows IEEE Standard 754, section 4. This kind of rounding is sometimes called round half to even or banker's rounding. It minimizes rounding errors that result from consistently rounding a midpoint value in a single direction. It is equivalent to calling the Round(Decimal, MidpointRounding) method with a mode argument of MidpointRounding.ToEven.

OhBeWise
  • 5,350
  • 3
  • 32
  • 60
Habib
  • 219,104
  • 29
  • 407
  • 436
  • This confirms the default, but does not add up with OP's first example. Why is it **rounding to odd**? I am encountering this behavior myself, irregularly, and I cannot explain it. – Timo May 27 '16 at 09:09
  • @Timo Can you supply examples of when this occurs? – Erik Kinding May 29 '17 at 13:39
  • @ErikKinding Been a year! I don't have examples anymore unfortunately. My machine produces `7.64` from `Decimal.Round(7.635m, 2)` as expected, I see. Does yours still produce `7.63`, as in your original post? – Timo May 29 '17 at 19:55
  • @Timo Actually no, when testing it out... Maybe they applied a patch? I'm getting 7.64 regardless of MidpointRounding. – Erik Kinding May 30 '17 at 09:00
  • 1.5 will round to 2, 2.5 will also default round to 2. .5-Numbers will go to the nearest even number by default. – BotMaster3000 Jun 14 '18 at 06:24
3

From Math.Round(Decimal, Int32) Method

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.

This method is equivalent to calling the Round method with a mode argument of MidpointRounding.ToEven. If there is a single non-zero digit in d to the right of the decimals decimal position and its value is 5, the digit in the decimals position is rounded up if it is odd, or left unchanged if it is even. If d has fewer fractional digits than decimals, d is returned unchanged.

Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
0

The reason is they implemented a method following IEEE Standard 754, section 4. This is called rounding to nearest or sometimes bankers rounding.

It's just one of many ways to do rounding and they choose this one. See: http://en.wikipedia.org/wiki/Bankers_rounding

And for more information: Why does .NET use banker's rounding as default?

Community
  • 1
  • 1
GreenEyedAndy
  • 1,485
  • 1
  • 14
  • 31