By Darin Dimitrov


2008-11-22 19:51:53 8 Comments

According to the documentation, the decimal.Round method uses a round-to-even algorithm which is not common for most applications. So I always end up writing a custom function to do the more natural round-half-up algorithm:

public static decimal RoundHalfUp(this decimal d, int decimals)
{
    if (decimals < 0)
    {
        throw new ArgumentException("The decimals must be non-negative", 
            "decimals");
    }

    decimal multiplier = (decimal)Math.Pow(10, decimals);
    decimal number = d * multiplier;

    if (decimal.Truncate(number) < number)
    {
        number += 0.5m;
    }
    return decimal.Round(number) / multiplier;
}

Does anybody know the reason behind this framework design decision?

Is there any built-in implementation of the round-half-up algorithm into the framework? Or maybe some unmanaged Windows API?

It could be misleading for beginners that simply write decimal.Round(2.5m, 0) expecting 3 as a result but getting 2 instead.

5 comments

@Omid Sadeghi 2017-03-26 14:44:22

Use another overload of Round function like this:

decimal.Round(2.5m, 0,MidpointRounding.AwayFromZero)

It will output 3. And if you use

decimal.Round(2.5m, 0,MidpointRounding.ToEven)

you will get banker's rounding.

@shortstuffsushi 2017-04-13 16:47:55

This doesn't answer the question of why Banker's Rounding was chosen as the default.

@Ostemar 2011-07-03 09:09:41

The other answers with reasons why the Banker's algorithm (aka round half to even) is a good choice are quite correct. It does not suffer from negative or positive bias as much as the round half away from zero method over most reasonable distributions.

But the question was why .NET use Banker's actual rounding as default - and the answer is that Microsoft has followed the IEEE 754 standard. This is also mentioned in MSDN for Math.Round under Remarks.

Also note that .NET supports the alternative method specified by IEEE by providing the MidpointRounding enumeration. They could of course have provided more alternatives to solving ties, but they choose to just fulfill the IEEE standard.

@Henk Holterman 2013-03-14 09:45:14

So, why does IEEE 754 follow bankers rounding? This (still good) answer just passes the bucket.

@Ostemar 2013-04-12 07:55:22

@HenkHolterman Probably due to what is mentioned in the other answers (and as I summarized); it does not suffer (too much) from negative or positive bias and as such makes for a more resonable default for most distributions and problem domains.

@Stijn 2014-04-02 08:16:50

@Brandon Barkley 2016-02-03 14:27:11

I think it's interesting because IEEE 754 is the standard for floating point numbers of which Decimal is not. Maybe it follows IEEE 754 so that the same algorithm is used for rounding Double as Decimal.

@Pablo H 2018-03-23 18:27:28

@BrandonBarkley A Decimal or decimal is a floating point number, and IEEE 754 does include decimal floating point numbers.

@Brandon Barkley 2018-05-21 04:03:53

Interesting. I had not really pondered how decimal numbers were rendered and stored.

@MestreLion 2018-10-26 10:33:58

@HenkHolterman : or one could ague that Microsoft passed the bucket

@Ian Ringrose 2010-01-22 12:58:04

Decimals are mostly used for money; banker’s rounding is common when working with money. Or you could say.

It is mostly bankers that need the decimal type; therefore it does “banker’s rounding”

Bankers rounding have the advantage that on average you will get the same result if you:

  • round a set of “invoice lines” before adding them up,
  • or add them up then round the total

Rounding before adding up saved a lot of work in the days before computers.

(In the UK when we went decimal banks would not deal with half pence, but for many years there was still a half pence coin and shop often had prices ending in half pence – so lots of rounding)

@John Tyree 2013-12-13 22:30:27

"Decimals are mostly used for money" ... and everything else that isn't an integer.

@Ian Ringrose 2013-12-14 13:08:14

@JohnTyree, Not true most of the time a double/float is used when it is not an integer. see stackoverflow.com/questions/2545567/…

@John Tyree 2013-12-16 02:59:39

Wow. Ridiculous mistake on my part. Decmials, yes. Decimals, no. For posterity, I agree with the original sentiment here.

@JustAMartin 2016-06-17 09:55:03

Bankers might like bankers' rounding, but bookkeepers might not be fans of it, they say that 0.005 difference should round lead to round up by 0.01, not depending whether it is odd or even number.

@Michael Stum 2008-11-22 19:59:54

While I cannot answer the question of "Why did Microsoft's designers choose this as the default?", I just want to point out that an extra function is unnecessary.

Math.Round allows you to specify a MidpointRounding:

  • ToEven - When a number is halfway between two others, it is rounded toward the nearest even number.
  • AwayFromZero - When a number is halfway between two others, it is rounded toward the nearest number that is away from zero.

@chris 2009-03-06 19:10:57

And as I've mentioned in related threads, make sure that you're consistent in your rounding - if you sometimes do rounding in the database, and sometimes in .net, you will have strange, one cent errors that will take you weeks to figure out.

@E.J. Brennan 2010-01-22 13:10:25

A client once paid me over $40,000 to track down an $0.11 rounding error between two numbers that were both just shy of 1 BILLION dollars; the $0.11 was due to a difference in the 8th digit rounding error between a mainframe and SQL Server. Talk about a perfectionist!

@royse41 2010-09-10 10:52:03

@EJB - i'd probably be a perfectionist if i was dealing with a billion dollars ;-)

@Matthieu N. 2011-03-08 02:30:55

@E.J. Brennan: It took you $40k to figure that out? I see problems like this all the time, rounding is cause #1, double/float normalization is cause #2, programmer error #3 - #3 can be immediately set to #1 if there are no predefined test cases. btw can you please put me in contact with your billionare client, i think i could find a few more $40k bugs in his system too! :D

@Brian 2011-06-20 16:52:46

@seanxe: Or if you'd seen Office Space. Seriously, whenever you see mysterious, tiny inaccuracies in money, solving the mystery of exactly how they are happening is almost always a good idea. It's possible you'll decide not to fix bugs, but knowing the underlying cause still has value. I bet many people who work with money are happy to notice even tiny inaccuracies.

@Ian Boyd 2011-09-09 14:01:13

+1 for listing alternative rounding methods already in .NET.

@phoog 2011-12-02 23:56:59

"Why did Microsoft's designers choose this as the default?" They didn't; the IEEE did. See Ostemar's answer: stackoverflow.com/a/6562018/385844 (sorry for snarky wording, but if I had a nickel for every developer I met who thought that "Microsoft had a bug in their rounding routines" ...)

@mskfisher 2012-04-20 15:22:40

@Matthieu N.: Maybe his hourly rate is $80k. :)

@Luaan 2014-02-13 11:30:53

@E.J.Brennan This usually isn't about perfectionism but rather about the (stupid, stupid) laws. I've had to do a similar thing (rounding "errors" related to "cents" being used in card payments but not cash payments). The error made up about $0.1 a year, but took almost a month to properly "fix" (and the customer still calls us once in a while when he gets scared by reports not showing rounded values, and I have to explain once again why that is correct, by logic and law). The fine for having such a $0.1 error when a tax officer comes around? Up to $100k. Most laws are ridiculous :)

@Kibbee 2008-11-22 19:57:14

Probably because it's a better algorithm. Over the course of many roundings performed, you will average out that all .5's end up rounding equally up and down. This gives better estimations of actual results if you are for instance, adding a bunch of rounded numbers. I would say that even though it isn't what some may expect, it's probably the more correct thing to do.

@jk. 2010-01-22 13:04:11

assuming you have an flat distribution of odd and even inputs of course

@Ian Boyd 2011-09-09 14:01:41

+1 for better algorithm, although Ostemar has the actual answer (stackoverflow.com/questions/311696/…)

@Kibbee 2011-09-09 14:13:03

@Ian, I give that answer +1 as well. Anyway we can get the "accepted answer moved" Maybe the OP can do this. The actual answer to "why" it uses this method is half way down the page. Although I quite like the rep boost I get about once a week from this answer.

@Ostemar 2011-09-25 17:40:51

@Kibbee - thanks for pushing up my answer. I guess it's up to the OP to change the accepted answer as he sees fit?

@paul23 2017-11-09 06:07:37

-1 for stating it's a better algorithm. - Given a random sample of number using banker's rounding you will end up having more numbers at even positions than odd positions. - It is only after you average those numbers that you get again a similar spread to the original distribution. - However if you for example would plot this data in a scatter plot one might see artificial grouping.

@Mr.Z 2018-03-28 22:13:13

For future visitors, Dango's answer (stackoverflow.com/a/7360463/1204599) complements this one well, and provides an excellent example demonstrating how the option MidpointRounding.ToEven can yield more accurate results.

Related Questions

Sponsored Content

63 Answered Questions

[SOLVED] Round to at most 2 decimal places (only if necessary)

19 Answered Questions

[SOLVED] Why is Dictionary preferred over Hashtable in C#?

26 Answered Questions

[SOLVED] Why not inherit from List<T>?

15 Answered Questions

[SOLVED] How do I round a decimal value to 2 decimal places (for output on a page)

16 Answered Questions

[SOLVED] Difference between decimal, float and double in .NET?

29 Answered Questions

[SOLVED] How to round a number to n decimal places in Java

5 Answered Questions

21 Answered Questions

[SOLVED] Sending email in .NET through Gmail

5 Answered Questions

[SOLVED] Why does Math.round(0.49999999999999994) return 1?

15 Answered Questions

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

  • 2009-06-10 19:51:05
  • jeffu
  • 231586 View
  • 369 Score
  • 15 Answer
  • Tags:   .net rounding

Sponsored Content