Once and for all: Do not use double for money
Published January 11th, 2008 in JavaThe discussion on how to represent money in applications pops up regularly . Funny lots of people still use double to represent money. During my interviews some people use double for money. Once and for all: Do not use double. Double cannot represent all amounts of money and it has rounding problems. Use a Money class. Represent the amount with a BigDecimal in cents and use BigDecimal.ROUND_HALF_EVEN as your rounding method. Use a distribute algorithm to distribute money to severel slots without losing cents.
Read more about a money class from Martin Fowler or this TSS discussion. Anders writes about Money in .NET.
Rant off. Thanks for not using double anymore.
11 Responses to “Once and for all: Do not use double for money”
- 1 Pingback on Jan 14th, 2008 at 8:36 am
- 2 Pingback on Jan 14th, 2008 at 2:55 pm
What do you mean with “Use a distribute algorithm to distribute money to severel slots without loosing cents.”? Could you please explain this further? Anyway thanks for the links, good discussions there.
@digital.alterego: Fowler calls it allocate I guess. You have 3 people and need to distribute (allocate) 10 EUR to them. 10/3 = 3.33 in cents, which means 1 cent is lost. Distributing 10 EUR correctly will result in 3 buckets [3.33, 3.33, 3.34].
I always distribute as [3.33, 3.33, 3.33] and then deposit 0.01 into my own secret account.
The comic hero, I´m really honoured.
A lot of people tried this, most of them got caught when getting greedy :-)
Quote:
————————–
I always distribute as [3.33, 3.33, 3.33] and then deposit 0.01 into my own secret account.
————————–
Just make sure you don’t mess up on some mundane detail like putting a decimal point in the wrong place.
But seriously, it’s been my opinion for a while that using float or double should cause a compiler warning optionally suppressed by a compiler flag. I believe the only place a typical programmer would run into floats being used correctly would be 3D graphics programming.
@Greg: I have the same feeling. Developers using double or float do use the wrong type in most cases except for 3D graphics or statistics.
I don’t know about USA, but in Europe you would use ROUND_HALF_UP for money rounding!?
ROUND_HALF_EVEN is called fair rounding because it distributes the error. It’s also called bankers rounding.
http://en.wikipedia.org/wiki/Rounding#Round-to-even_method
“Rounding mode to round towards the “nearest neighbor” unless both neighbors are equidistant, in which case, round towards the even neighbor. Behaves as for ROUND_HALF_UP if the digit to the left of the discarded fraction is odd; behaves as for ROUND_HALF_DOWN if it’s even. Note that this is the rounding mode that minimizes cumulative error when applied repeatedly over a sequence of calculations.”
http://java.sun.com/j2se/1.5.0/docs/api/java/math/BigDecimal.html#ROUND_HALF_EVEN
http://en.wikipedia.org/wiki/Rounding#Round-to-even_method:
“The origin of the term bankers’ rounding is more obscure. If this rounding method was ever a standard in banking, the evidence has proved extremely difficult to find. To the contrary, section 2 of the European Commission report The Introduction of the Euro and the Rounding of Currency Amounts [2] suggests that there had previously been no standard approach to rounding in banking.”