Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

BigDecimal and Money

I've researched and found that when dealing with currency, the best way to go about doing calculations is by the BigDecimal class.

With that in mind, I'm working on a code that converts various types of foreign currency into US currency and vice-versa (specifically, a cashregister that takes foreign currency and converts it into US money, computes the change and returns this amount to the customer in foreign currency).

As of now, many of the methods use double and two of them take in int as a parameter to be used in computing the US currency.

Question:

Since I want to use the BigDecimal class in my calculations, should I change all my methods that make calculations involving doubles to a BigDecimal?

like image 846
Wormhole99 Avatar asked Mar 31 '12 20:03

Wormhole99


2 Answers

Yes, you should change all floats or doubles to take either ints, longs or BigDecimals.

Floats and doubles are not precise for financial calculations. It's a very good idea to use the Money pattern to deal with amounts and currencies (it's a special type of Quantity). To maintain a list of moneys possibly in multiple currencies, what you're effectively doing is a MoneyBag, a collection of Money that can then sum all values given a target currency and a CurrencyExchangeService (currency conversion rates should also be stored as BigDecimals).

Rounding should be done after every operation according to the number of desired decimal places and the rounding algorithm. The number of decimal places is normally a property of the Currency (look, e.g., at ISO 4217); unless a different number is desired (like when pricing gasoline, for example).

You should definitely look at Fowler's examples; but I've also created a very simple uni-currency Money class for an exercise. It uses dollars only and rounds to 2 decimal places; but it's still a good base for future extensions.

like image 75
Jordão Avatar answered Sep 21 '22 22:09

Jordão


Yes, BigDecimal is certainly the correct way (floating point almost never). Also in JDBC.

But having said that, there is an issue with rounding. In some cases 6 decimals are legally required in european software. In general you will want to round on 2 places in every step. If you have a quantity with 2 decimals and a price, you'll get 4 decimals, and have to round. So to make the ugly BigDecimal interface even uglier, you probably need some help functions (multiplyRounded?).

like image 26
Joop Eggen Avatar answered Sep 23 '22 22:09

Joop Eggen