Representing Monetary Values in Java

JavaCurrencyBigdecimal

Java Problem Overview


I understand that BigDecimal is recommended best practice for representing monetary values in Java. What do you use? Is there a better library that you prefer to use instead?

Java Solutions


Solution 1 - Java

BigDecimal all the way. I've heard of some folks creating their own Cash or Money classes which encapsulate a cash value with the currency, but under the skin it's still a BigDecimal, probably with BigDecimal.ROUND_HALF_EVEN rounding.

Edit: As Don mentions in his answer, there are open sourced projects like timeandmoney, and whilst I applaud them for trying to prevent developers from having to reinvent the wheel, I just don't have enough confidence in a pre-alpha library to use it in a production environment. Besides, if you dig around under the hood, you'll see they use BigDecimal too.

Solution 2 - Java

It can be useful to people arriving here by search engines to know about JodaMoney: http://www.joda.org/joda-money/.

Solution 3 - Java

I'm not expressing my opinion here, but there are quite good arguments against BigDecimal that someone should probably throw out:

http://lemnik.wordpress.com/2011/03/25/bigdecimal-and-your-money/

Solution 4 - Java

A convenient library that I ran into earlier is the Joda-Money library. One of its implementations is indeed based on BigDecimal. It is based on the ISO-4217 specification for currencies and can support a customized currency list (loaded via CVS).

This library has a small number of files that one can quickly go through if modifications are needed. Joda-Money is published under the Apache 2.0 license.

Solution 5 - Java

If you are just using dollars and cents, I'd use a long (offset by 2 decimal places). If you need more detail, big decimal may be the way to go.

Either way, I'd probably extend the class to have a .toString() that uses the correct format, and as a place to put other methods that might come up (For a long, multiplying and dividing will go awry if the decimal isn't adjusted)

Also, if you use define your own class and interface, then you can replace the implementation at will.

Solution 6 - Java

BigDecimal or another fixed point representation is what is generally needed for money.

Floating point (Double, Float) representations and calculations are inexact, leading to erroneous results.

Solution 7 - Java

You have to be so careful when dealing with time and money.

When you are working with money, I hope everybody should know never to use a float or a double.

But I am unsure about BigDecimal.

In most cases you'll be fine if you just keep track of cents in a int or long. This way you never deal with a decimal place.

You only display dollars when you print it. Always work with cents internal using integers. This may be tricky if need to divide or need to use Math.abs().

However, you might care able half a cent, or even one hundredth of a cent. I don't know what's a good way to do this. You might just need to deal with thousandth of cents and use a long. Or maybe you'll be forced to use BigDecimal

I would do a lot more reading on this, but ignore everybody who starts talking about using a float or double to represent money. They are just asking for trouble.

I feel my advice isn't complete, so please put more though into it. You are dealing with dangerous types!

Solution 8 - Java

Creating a Money class is the way to go. Using BigDecimal( or even an int) underneath. Then using Currency class to define rounding convention.

Unfortunately without operator overloading Java makes it quite unpleasant creating such basic types.

Solution 9 - Java

There is a better library, timeandmoney. IMO, it far superior to the libraries provided by the JDK for representing these 2 concepts.

Solution 10 - Java

Definitely not BigDecimal. There are so many special rules for rounding and presentation that you have to worry about.

Martin Fowler recommends the implementation of a dedicated Money class to represent currency amounts, and that also implements rules for currency conversion.

Solution 11 - Java

Hey, here's a very interesting article on BigDecimal, and an illustrative example of why sometimes it is used instead of doubles. http://www.opentaps.org/docs/index.php/How_to_Use_Java_BigDecimal:_A_Tutorial">BigDecimal Tutorial.

Solution 12 - Java

You can use the DecimalFormat class when ultimately displaying a currency value. It provides localization support and is pretty extensible.

Solution 13 - Java

I would encapsulate BigDecimal in Money class that also has a currency just as someone mentioned above. The important thing is that you do an extreme amount of unit tests and especially if working with different currencies. Also it is a good idea if you add a convinient constructor that takes a string or a factory method that does the same so that you can write your tests something like this:

   assertEquals(Money.create("100.0 USD").add("10 GBP"),Money.create("116 USD"));

Solution 14 - Java

There are always constraints and specifics involved. Anyone without sufficient experience to appreciate the subtle issues outlined in the following article should seriously reconsider before dealing with real-world financial data:

http://lemnik.wordpress.com/2011/03/25/bigdecimal-and-your-money

BigDecimal is hardly the only correct representation or the only piece of the puzzle. Given certain conditions, using a Money class backed by cents stored as an integer could be sufficient and would be much faster than BigDecimal. Yes, that implies the use of dollars as currency and limits amounts but such constraints are perfectly acceptable for many use cases and all currencies have special cases for rounding and sub-denominations anyway, so there's no "universal" solution.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiondshawView Question on Stackoverflow
Solution 1 - JavaninesidedView Answer on Stackoverflow
Solution 2 - JavaIñaki Ibarrola AtxaView Answer on Stackoverflow
Solution 3 - JavaorbfishView Answer on Stackoverflow
Solution 4 - JavabasharView Answer on Stackoverflow
Solution 5 - JavaBill KView Answer on Stackoverflow
Solution 6 - JavaKen GentleView Answer on Stackoverflow
Solution 7 - JavaPyrolisticalView Answer on Stackoverflow
Solution 8 - JavaKozyarchukView Answer on Stackoverflow
Solution 9 - JavaDónalView Answer on Stackoverflow
Solution 10 - JavalindelofView Answer on Stackoverflow
Solution 11 - Javaarg20View Answer on Stackoverflow
Solution 12 - JavamyanswerView Answer on Stackoverflow
Solution 13 - JavaPer ArnengView Answer on Stackoverflow
Solution 14 - JavaCraigView Answer on Stackoverflow