william.eyidi
william.eyidi

Reputation: 2365

What class to use to represent currencies in Java?

I am working on a finacial project developed in Java, I would like to:

I would like to know what is the best Java class to use to make the currencies work properly. It came down to these two choices:

  1. BigDecimal
  2. Double

Can you explain me a bit more what is the best choice for this endeavor?

Upvotes: 2

Views: 409

Answers (4)

DavidPostill
DavidPostill

Reputation: 7921

From this answer by zneak:

Because floats and doubles cannot accurately represent the base 10 multiples we use for money. This issue isn't just for Java, it's for any programming language that uses native floating-point types, as it stems from how computers handle floating-point numbers by default.

This is how an IEEE-754 floating-point number works: it dedicates a bit for the sign, a few bits to store an exponent for the base, and the rest for a multiple of that elevated base. This leads to numbers like 10.25 being represented in a form similar to 1025 * 10^-2; except that instead of the base being 10, for floats and doubles, it's two (so that would be 164 * 2^-4).

Even in base 10, this notation cannot accurately represent most simple fractions. For instance, you can't represent 1/3 as a multiple of a power of 10: you would need to store an infinite amount of 3's and an infinitely large negative exponent, and you simply can't do that. However, for the purpose of money, in most scenarios all you need is to be able to store multiples of 10-2, so it's not too bad.

Just as some fractions can't be represented exactly as a multiples of a power of ten, some of them can't be represented exactly as a multiple of a power of two, either. In fact, the only fractions of a hundred between 0/100 and 100/100 (which are significant when dealing with money because they're integer cents) that can be represented exactly as an IEEE-754 binary floating-point number are 0, 0.25, 0.5, 0.75 and 1. All the others are off by a small amount.

Representing money as a double or float will probably look good at first as the software rounds off the tiny errors, but as you perform more additions, subtractions, multiplications and divisions on inexact numbers, you'll lose more and more precision as the errors add up. This makes floats and doubles inadequate for dealing with money, where perfect accuracy for multiples of base 10 powers is required.

A solution that works in just about any language is to use integers instead, and count cents. For instance, 1025 would be $10.25. Several languages also have built-in types to deal with money. Among others, Java has the BigDecimal class, and C# has the decimal type.

Upvotes: 0

user207421
user207421

Reputation: 310988

You cannot use floating-point for money.

You must use a decimal radix, therefore BigDecimal.

The reason is that accounting is carried out in decimal radix and you have to agree with it.

Also there are concepts like "banker's rounding" you must implement accurately, which are provided by java.math.RoundingMode.

Upvotes: 1

william.eyidi
william.eyidi

Reputation: 2365

I was looking at the BigDecimal API, and the class provide a high precision for the operation of rounding and converting. here is what I read there you could find it interesting.

The BigDecimal class gives its user complete control over rounding behavior. If no rounding mode is specified and the exact result cannot be represented, an exception is thrown; otherwise, calculations can be carried out to a chosen precision and rounding mode by supplying an appropriate MathContext object to the operation. In either case, eight rounding modes are provided for the control of rounding. Using the integer fields in this class (such as ROUND_HALF_UP) to represent rounding mode is largely obsolete; the enumeration values of the RoundingMode enum, (such as RoundingMode.HALF_UP) should be used instead.

the link is here

Upvotes: 0

Ruchira Gayan Ranaweera
Ruchira Gayan Ranaweera

Reputation: 35577

My suggestion is BigDecimal

Check this out.

This is a project to develop code for manipulating basic concepts in recurring domains such as time and money. The design principles followed here are explained in Part III of the book Domain-Driven Design. Read the credits here and release notes here. For some of the conceptual workings, you can read this explanation of time algebra and this explanation of interval math.

In here they also used BigDecimal. And again it is helpful you to Rounding and Scaling in BigDecimal.

Upvotes: 2

Related Questions