Popular Java library classes rarely needed . . .

BigDecimal Doesn't Belong in Real-World Applications

©Conrad Weisert
September 1, 2012

NOTE: This article may be reproduced and circulated freely, as long as the copyright credit is included.

Surprising advice

Many Java experts recommend using Java's library class BigDecimal whenever Java's built-in "primitive" numeric data types provide insufficient precision. This occurs commonly, for example, in dealing with amounts of money. a central part of financial applications. Even the highly respected collection of advice from Joshua Bloch nudges the reader in that direction. After showing an example in which floating-point representation of U.S. dollars yields an incorrect result, the author advises:1

If you run the program, you'll find that you . . . have $0.3999999999999999 left. This is the wrong answer! The right way to solve this problem is to use BigDecimal, int, or long for monetary calculations

|
|

An alternative to using BigDecimal is to use int or long, depending on the amounts involved and to keep track of the decimal point yourself.

and David Flanagan explains:2

Because it uses a decimal rather than binary floating-point representations, it is not subject to rounding errors that float and double types are. This makes BigDecimal well-suited to financial and similar applications.

No, no, no! Why do experts keep forgetting that Java is an object oriented programming language and books about Java are supposed to be about object-oriented programming?

Not so big decimal

If we examine typical uses of BigDecimal it turns out that very few of them actually need a numeric representation that's unusually big. They're just using the decimal scaling capability to mimic what they might have specified in PL/I as FIXED DECIMAL(9,2) or in COBOL as PICTURE S9(7)V99. The ability to handle monstrously long numbers in BigDecimal just imposes unnecessary complexity and inefficiency.

An object-oriented solution

Joshua Bloch had the right idea when he suggested, as an alternative, using long to represent amounts of money—but not about "keeping track of the decimal point yourself".   The obvious choice for representing amounts of money is to use a Money class, such as the one on this web site. The Money class has to keep track of the scaling, of course, but applications that use it just use the familiar units of the currency they're working with.

In fact the internal (hidden member) data can be either long or double, in integer units of the smallest increment (e.g. U.S. ¢) but certainly not BigDecimal. So, if BigDecimal is unsuitable for amounts of money, what is it good for? So far, we haven't encountered any practical use for it in a real business or scientific application.

What about BigInteger?

Java textbooks often present BigDecimal and BigInteger together as if there were some relationship between them. However, they're entirely different, both in their internal workings and in the range of problems they're designed to solve.

A long (64-bit) integer can represent numbers between ±263 or roughly 1020. Since this magnitude approaches the number of atoms in the universe, it's extremely unlikely that any data type with a unit of measure would require values having a greater magnitude. In particular, financial applications, despite serious inflation, are not called upon to manipulate quintillions of dollars.

If we don't need BigInteger for data having a unit of measure or for typical business or scientific applications, what good is it?   It can be very useful in dealing with pure numbers, in such areas as:


1Effective Java, second edition, Addison-Wesley, ISBN 978-0-321-35668-0, p. 219.
2Java in a Nutshell, fifth edition, O'Reilly, ISBN 978-0-596-00773-7, p. 543.

Last modified December, 2014

Return to IDI home page
Technical articles