A BigDecimal is an exact way of representing numbers. A Double has a certain precision. Working with doubles of various magnitudes (say d1=1000.0 and d2=0.001) could result in the 0.001 being dropped altogether when summing as the difference in magnitude is so large. With BigDecimal this would not happen.

The disadvantage of BigDecimal is that it's slower, and it's a bit more difficult to program algorithms that way (due to + - * and / not being overloaded).

If you are dealing with money, or precision is a must, use BigDecimal. Otherwise Doubles tend to be good enough.

I do recommend reading the javadoc of BigDecimal as they do explain things better than I do here :)

Answer from extraneon on Stack Overflow
🌐
Reddit
reddit.com › r/java › double vs bigdecimal in financial programming
r/java on Reddit: Double vs BigDecimal in financial programming
May 22, 2018 -

Everyone says that BigDecimal should be used when dealing with money but it’s much slower and takes more memory than double. I would think this would be especially important in high frequency low-latency applications like trading. Do people actually use BigDecimal in such systems or do they use doubles with some kind of workaround to handle the precision issue?

Edit: I do have experience working on trading and risk systems and I see doubles used much more often than BigDecimal so I was curious to see if this is more common in actual practice. Most of the systems I worked on only need precision to the penny so I wonder if that’s the reason?

Also, BigDecimal is a pain to use and code written with it look much uglier than plain doubles.

🌐
DZone
dzone.com › data engineering › data › why you should never use float and double for monetary calculations
Why You Should Never Use Float and Double for Monetary Calculations
August 21, 2018 - Float and double are bad for financial (even for military use) world, never use them for monetary calculations. If precision is one of your requirements, use BigDecimal instead. Let's explore this problem with the help of an example: All floating ...
🌐
JA-VA Code
java-performance.info › home › bigdecimal vs. double in financial calculations
BigDecimal vs. Double: Precision for Financial Accuracy
October 9, 2023 - When should I use BigDecimal over Double in financial calculations? Use BigDecimal when precision is crucial, such as in compound interest, currency conversion, tax calculations, and risk assessments.
🌐
Frankel
blog.frankel.ch › bigdecimal-vs-double
double, BigDecimal, or Fixed-Point?
June 14, 2026 - The short answer is no. The real answer is: it depends on your computational context: the precision you need, the rounding rules you must follow, and the performance budget you have.
🌐
Learn INQuiZitively
linqz.io › 2019 › 02 › choosing-data-type-for-monetary-calculation-in-java-float-double-or-bigdecimal.html
Choosing data type for monetary Calculation (In Java)— Float ? Double ? Or Bigdecimal - Learn INQuiZitively
If negative, the unscaled value of the number is multiplied by ten to the power of the negation of the scale. The value of the number represented by the BigDecimal is therefore (unscaledValue × 10-scale). ... Above facts point to the fact that float will have more precision loss than double, thus ...
Top answer
1 of 8
33

I can see four basic ways that double can screw you when dealing with currency calculations.

Mantissa Too Small

With ~15 decimal digits of precision in the mantissa, you are you going to get the wrong result any time you deal with amounts larger than that. If you are tracking cents, problems would start to occur before 1013 (ten trillion) dollars.

While that's a big number, it's not that big. The US GDP of ~18 trillion exceeds it, so anything dealing with country or even corporation sized amounts could easily get the wrong answer.

Furthermore, there are plenty of ways that much smaller amounts could exceed this threshold during calculation. You might be doing a growth projection or a over a number of years, which results in a large final value. You might be doing a "what if" scenario analysis where various possible parameters are examined and some combination of parameters might result in very large values. You might be working under financial rules which allow fractions of a cent which could chop another two orders of magnitude or more off of your range, putting you roughly in line with the wealth of mere individuals in USD.

Finally, let's not take a US centric view of things. What about other currencies? One USD is worth is worth roughly 13,000 Indonesian Rupiah, so that's another 2 orders of magnitude you need to track currency amounts in that currency (assuming there are no "cents"!). You're almost getting down to amounts that are of interest to mere mortals.

Here is an example where a growth projection calculation starting from 1e9 at 5% goes wrong:

method   year                         amount           delta
double      0             $ 1,000,000,000.00
Decimal     0             $ 1,000,000,000.00  (0.0000000000)
double     10             $ 1,628,894,626.78
Decimal    10             $ 1,628,894,626.78  (0.0000004768)
double     20             $ 2,653,297,705.14
Decimal    20             $ 2,653,297,705.14  (0.0000023842)
double     30             $ 4,321,942,375.15
Decimal    30             $ 4,321,942,375.15  (0.0000057220)
double     40             $ 7,039,988,712.12
Decimal    40             $ 7,039,988,712.12  (0.0000123978)
double     50            $ 11,467,399,785.75
Decimal    50            $ 11,467,399,785.75  (0.0000247955)
double     60            $ 18,679,185,894.12
Decimal    60            $ 18,679,185,894.12  (0.0000534058)
double     70            $ 30,426,425,535.51
Decimal    70            $ 30,426,425,535.51  (0.0000915527)
double     80            $ 49,561,441,066.84
Decimal    80            $ 49,561,441,066.84  (0.0001678467)
double     90            $ 80,730,365,049.13
Decimal    90            $ 80,730,365,049.13  (0.0003051758)
double    100           $ 131,501,257,846.30
Decimal   100           $ 131,501,257,846.30  (0.0005645752)
double    110           $ 214,201,692,320.32
Decimal   110           $ 214,201,692,320.32  (0.0010375977)
double    120           $ 348,911,985,667.20
Decimal   120           $ 348,911,985,667.20  (0.0017700195)
double    130           $ 568,340,858,671.56
Decimal   130           $ 568,340,858,671.55  (0.0030517578)
double    140           $ 925,767,370,868.17
Decimal   140           $ 925,767,370,868.17  (0.0053710938)
double    150         $ 1,507,977,496,053.05
Decimal   150         $ 1,507,977,496,053.04  (0.0097656250)
double    160         $ 2,456,336,440,622.11
Decimal   160         $ 2,456,336,440,622.10  (0.0166015625)
double    170         $ 4,001,113,229,686.99
Decimal   170         $ 4,001,113,229,686.96  (0.0288085938)
double    180         $ 6,517,391,840,965.27
Decimal   180         $ 6,517,391,840,965.22  (0.0498046875)
double    190        $ 10,616,144,550,351.47
Decimal   190        $ 10,616,144,550,351.38  (0.0859375000)

The delta (difference between double and BigDecimal first hits > 1 cent at year 160, around 2 trillion (which might not be all that much 160 years from now), and of course just keeps getting worse.

Of course, the 53 bits of Mantissa mean that the relative error for this kind of calculation is likely to be very small (hopefully you don't lose your job over 1 cent out of 2 trillion). Indeed, the relative error basically holds fairly steady through most of the example. You could certainly organize it though so that you (for example) subtract two various with loss of precision in the mantissa resulting in an arbitrarily large error (exercise up to reader).

Changing Semantics

So you think you are pretty clever, and managed to come up with a rounding scheme that lets you use double and have exhaustively tested your methods on your local JVM. Go ahead and deploy it. Tomorrow or next week or whenever is worst for you, the results change and your tricks break.

Unlike almost every other basic language expression and certainly unlike integer or BigDecimal arithmetic, by default the results of many floating point expressions don't have a single standards defined value due to the strictfp feature. Platforms are free to use, at their discretion, higher precision intermediates, which may result in different results on different hardware, JVM versions, etc. The result, for the same inputs, may even vary at runtime when the method switches from interpreted to JIT-compiled!

If you had written your code in the pre-Java 1.2 days, you'd be pretty pissed when Java 1.2 suddenly introduces the now-default variable FP behavior. You might be tempted to just use strictfp everywhere and hope you don't run into any of the multitude of related bugs - but on some platforms you'd be throwing away much of the performance that double bought you in the first place.

There's nothing to say that the JVM spec won't again change in the future to accommodate further changes in FP hardware, or that the JVM implementors won't use the rope that the default non-strictfp behavior gives them to do something tricky.

Inexact Representations

As Roland pointed out in his answer, a key problem with double is that it doesn't have exact representations for some most non-integer values. Although a single non-exact value like 0.1 will often "roundtrip" OK in some scenarios (e.g., Double.toString(0.1).equals("0.1")), as soon as you do math on these imprecise values the error can compound, and this can be irrecoverable.

In particular, if you are "close" to a rounding point, e.g., ~1.005, you might get a value of 1.00499999... when the true value is 1.0050000001..., or vice-versa. Because the errors go in both directions, there is no rounding magic that can fix this. There is no way to tell if a value of 1.004999999... should be bumped up or not. Your roundToTwoPlaces() method (a type of double rounding) only works because it handled a case where 1.0049999 should be bumped up, but it will never be able to cross the boundary, e.g., if cumulative errors cause 1.0050000000001 to be turned into 1.00499999999999 it can't fix it.

You don't need big or small numbers to hit this. You only need some math and for the result to fall close to the boundary. The more math you do, the larger the possible deviations from the true result, and the more chance of straddling a boundary.

As requested here a searching test that does a simple calculation: amount * tax and rounds it to 2 decimal places (i.e., dollars and cents). There are a few rounding methods in there, the one currently used, roundToTwoPlacesB is a souped-up version of yours1 (by increasing the multiplier for n in the first rounding you make it a lot more sensitive - the original version fails right away on trivial inputs).

The test spits out the failures it finds, and they come in bunches. For example, the first few failures:

Failed for 1234.57 * 0.5000 = 617.28 vs 617.29
Raw result : 617.2850000000000000000000, Double.toString(): 617.29
Failed for 1234.61 * 0.5000 = 617.30 vs 617.31
Raw result : 617.3050000000000000000000, Double.toString(): 617.31
Failed for 1234.65 * 0.5000 = 617.32 vs 617.33
Raw result : 617.3250000000000000000000, Double.toString(): 617.33
Failed for 1234.69 * 0.5000 = 617.34 vs 617.35
Raw result : 617.3450000000000000000000, Double.toString(): 617.35

Note that the "raw result" (i.e., the exact unrounded result) is always close to a x.xx5000 boundary. Your rounding method errs both on the high and low sides. You can't fix it generically.

Imprecise Calculations

Several of the java.lang.Math methods don't require correctly rounded results, but rather allow errors of up to 2.5 ulp. Granted, you probably aren't going to be using the hyperbolic functions much with currency, but functions such as exp() and pow() often find their way into currency calculations and these only have an accuracy of 1 ulp. So the number is already "wrong" when it is returned.

This interacts with the "Inexact Representation" issue, since this type of error is much more serious than that from the normal mathematic operations which are at least choosing the best possible value from with the representable domain of double. It means that you can have many more round-boundary crossing events when you use these methods.

2 of 8
21

When you round double price = 0.615 to two decimal places, you get 0.61 (rounded down) but probably expected 0.62 (rounded up, because of the 5).

This is because double 0.615 is actually 0.6149999999999999911182158029987476766109466552734375.

🌐
LinkedIn
linkedin.com › pulse › why-we-should-use-bigdecimal-instead-double-java-financial-ismail
Why we should use BigDecimal instead double in java for financial systems
May 17, 2022 - So if we have a system where low latency is crucial than the decimal part of a number, we should go for double. But in financial or any other systems where each digit of decimal part are important, BigDecimal should be chosen over double/float.
Find elsewhere
🌐
iCert Global
icertglobal.com › home › community › using bigdecimal vs double for financial calculations involving currency data types?
Using BigDecimal vs Double for financial calculations involving currency data types? | iCert Global
Many decimal fractions (like 0.1) cannot be represented exactly in binary, leading to tiny precision errors that accumulate. For money, this is unacceptable. BigDecimal provides absolute precision because it handles numbers as integers with a scale.
🌐
DEV Community
dev.to › luke_tong_d4f228249f32d86 › beyond-double-essential-bigdecimal-practices-for-accurate-financial-calculations-52m1
Beyond double: Essential BigDecimal Practices for Accurate Financial Calculations - DEV Community
May 28, 2025 - If you’ve been around software development for a bit, especially anywhere near financial applications, you’ve probably heard the golden rule: don’t use double (or float) for money. It's common knowledge, and for good reason – floating-point arithmetic can lead to precision errors that are a nightmare in finance. The go-to solution is java.math.BigDecimal.
🌐
Medium
medium.com › @cancerian0684 › which-data-type-would-you-choose-for-storing-currency-values-like-trading-price-dd7489e7a439
Which data type would you choose for storing currency values like Trading Price? What’s your opinion about Float, Double and BigDecimal? | by Munish Chandel | Medium
August 15, 2018 - Float & Double are bad for financial (even for military use) world, never use them for monetary calculations. If precision is one of your requirements, use BigDecimal instead. Lets see the problem with the help of this example: All floating ...
🌐
Medium
medium.com › @qingedaig › java-bigdecimal-vs-double-vs-float-012c7149e550
Java BigDecimal vs double vs float | by Alice Dai | Medium
October 15, 2024 - Scientific Calculations: It’s suitable for scientific computations where a small level of inaccuracy is acceptable. Large Range: When you need to handle very large or very small numbers but don’t require the precision that BigDecimal offers. public class DoubleExample { public static void main(String[] args) { double price = 19.99; double tax = 0.07; double totalPrice = price + (price * tax); System.out.println("Total Price: " + totalPrice); } }
🌐
Blogger
javarevisited.blogspot.com › 2012 › 02 › java-mistake-1-using-float-and-double.html
Java Mistake 1 - Using float and double for monetary or financial calculation Example
A Currency class with discount() ... This is nonsense and a damn myth. Double is fine for financial calculations, given you understand its limitations, and only want cent precision....
Top answer
1 of 3
13

It all comes down to precision, and Java's BigDecimal seems the correct answer on that platform because it gives you the best support for specifying and preserving what can be highly variable precision.

A millionth of a cent is only 10-5 from a shift in payable amount, and it's not that hard to come up with a situation where that level of precision matters.

  1. Company A is publicly traded, with fifty million (5x106) shares outstanding and a current price of $10.
  2. Person B buys $1 of Company A, through a broker. They now own one-tenth of a share, or a one five-hundred-millionth of Company A. (10-7).
  3. Company A is found to be absurdly over-valued, and after a bit of a scandal winds up accepting a stock-swap purchase by Company C at a value of $1,000 (103), with each shareholder getting the equivalent number to be paid out equally to the shareholders in either cash or stock.
  4. How much cash or stock can Person B get? Note that if you get the number wrong, Person B (who happens to be an out-of-work lawyer in his 30s) can mess up the entire deal and possibly earn himself a paycheck by suing for his value lost plus legal fees.

Now, the valuation is fairly absurd on purpose, but the same "you need to get it right or it explodes" details even if the numbers are only off by a minuscule amount.

2 of 3
9

The right type to represent currency values depends of the application.

Two plausible choices are a type capable of exact arithmetic or a floating point type. Please remember two facts:

  1. In floating point arithmetic, usual algebraic identities (like commutativity and associativity) does not hold any more. They still hold in exact arithmetic.

  2. In exact arithmetic, it is not possible to work with functions other than polynomials, so we cannot use the square root or the exponential functions. Floating point arithmetics allows to use them.

In a double accounting personal finance software, exact arithmetic is preferrable. We expect all of the cashflows recorded to sum up to zero. Since this is an algebraic identity, we can only verify it if we use exact arithmetics. Here using a floating point would make the whole principe of double accounting useless.

In an internal software used by a clearing house, exact arithmetic is also mandatory, basically for the same reason as previously. There is a conservation principle, so that cashflows should always sum up to zero. Since the program has to satisfy an invariant of an algebraic nature, it must rely on exact arithmetics.

In a pricing or risk management software implementing methods of mathematical finance, complex computations reminescent of physics simulations are performed and expectations estimates are computed. The very nature of this problem require the use of floating point numbers.

Top answer
1 of 16
1335

Because floats and doubles cannot accurately represent the base 10 multiples that we use for money. This issue isn't just for Java, it's for any programming language that uses base 2 floating-point types.

In base 10, you can write 10.25 as 1025 * 10-2 (an integer times a power of 10). IEEE-754 floating-point numbers are different, but a very simple way to think about them is to multiply by a power of two instead. For instance, you could be looking at 164 * 2-4 (an integer times a power of two), which is also equal to 10.25. That's not how the numbers are represented in memory, but the math implications are the same.

Even in base 10, this notation cannot accurately represent most simple fractions. For instance, you can't represent 1/3: the decimal representation is repeating (0.3333...), so there is no finite integer that you can multiply by a power of 10 to get 1/3. You could settle on a long sequence of 3's and a small exponent, like 333333333 * 10-10, but it is not accurate: if you multiply that by 3, you won't get 1.

However, for the purpose of counting money, at least for countries whose money is valued within an order of magnitude of the US dollar, usually all you need is to be able to store multiples of 10-2, so it doesn't really matter that 1/3 can't be represented.

The problem with floats and doubles is that the vast majority of money-like numbers don't have an exact representation as an integer times a power of 2. In fact, the only multiples of 0.01 between 0 and 1 (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. As an analogy to the 0.333333 example, if you take the floating-point value for 0.01 and you multiply it by 10, you won't get 0.1. Instead you will get something like 0.099999999786...

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, errors will compound and you'll end up with values that are visibly not accurate. 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 Rust has the rust_decimal crate, and C# has the decimal type.

2 of 16
373

From Bloch, J., Effective Java, (2nd ed, Item 48. 3rd ed, Item 60):

The float and double types are particularly ill-suited for monetary calculations because it is impossible to represent 0.1 (or any other negative power of ten) as a float or double exactly.

For example, suppose you have $1.03 and you spend 42c. How much money do you have left?

System.out.println(1.03 - .42);

prints out 0.6100000000000001.

The right way to solve this problem is to use BigDecimal, int or long for monetary calculations.

Though BigDecimal has some caveats (please see the answer by zneak).

🌐
Quora
quora.com › What-is-the-difference-between-BigDecimal-vs-Double
What is the difference between BigDecimal vs Double? - Quora
Answer (1 of 6): Double is a wrapper for the Java native double type, a 64-bit floating point number. BigDecimal is arbitrary-precision arithmetic. It can represent numbers to as many bits of precision as you want to throw memory and time at. (Technically, it's limited to a 32 bit exponent, but ...
🌐
Jerickson
jerickson.net › double-trouble-dont-use-doubles-currency-accurate-decimals
Double Trouble (Don't use doubles for currency or accurate decimals) · JErickson.net
July 17, 2019 - We should avoid using double s at all when dealing with important decimal numbers. Remember: BigDecimal, not double or Double!
🌐
Don't Panic!
dontpanicblog.co.uk › home › currency and bigdecimal
Currency and BigDecimal - Don't Panic!
January 15, 2017 - So long as you realize that there are two types of number – approximate and exact – it’s easy to pick an appropriate representation. Floats and doubles are approximations. They are accurate to several decimal places but they’re always approximations. BigDecimal is exact.