Fundamentals 10 min read

Why double Is Inaccurate and How to Use BigDecimal Correctly in Java

This article explains why double precision numbers cannot represent many decimal values exactly, how BigDecimal achieves precise arithmetic through unscaled values and scale, and the proper ways to construct BigDecimal objects to avoid precision loss in Java applications.

macrozheng
macrozheng
macrozheng
Why double Is Inaccurate and How to Use BigDecimal Correctly in Java

BigDecimal, a type from the

java.math

package, is widely used for precise arithmetic in financial, e‑commerce, and payment systems. However, merely using

BigDecimal

does not guarantee accuracy if it is created incorrectly.

Why double Is Inaccurate

Computers operate in binary, so all numbers must be converted to binary for storage. While integer conversion is straightforward, many decimal fractions cannot be represented exactly in binary; for example, 0.1 becomes an infinite repeating binary fraction (0.0001100110011…). Consequently, double values are approximations, leading to precision errors.

The IEEE‑754 standard defines floating‑point representations, including 32‑bit single precision (float) and 64‑bit double precision (double). In Java,

float

and

double

store these approximations, which is why double‑based calculations can be imprecise.

How BigDecimal Ensures Precision

Internally, a

BigDecimal

consists of an unscaled value and a scale . The scale (accessible via

scale()

) indicates the number of digits to the right of the decimal point when non‑negative, or the power of ten to multiply when negative.

<code>public class BigDecimal extends Number implements Comparable<BigDecimal> {
    private final BigInteger intVal;
    private final int scale;
    private final transient long intCompact;
}</code>

For example, the number 123.123 is stored with an unscaled value of 123123 and a scale of 3. This representation allows exact storage of values like 0.1, which would otherwise be impossible with binary floating‑point.

Problems with BigDecimal(double)

Creating a

BigDecimal

from a double inherits the double’s approximation. For instance,

new BigDecimal(0.1)

yields a value of 0.1000000000000000055511151231257827021181583404541015625, losing the intended precision.

Creating Precise BigDecimal Instances

The reliable way to obtain an exact

BigDecimal

is to use a

String

constructor or

BigDecimal.valueOf

:

<code>BigDecimal recommend1 = new BigDecimal("0.1");
BigDecimal recommend2 = BigDecimal.valueOf(0.1);
</code>

Although

valueOf

internally calls

Double.toString

, it returns a canonical string representation that preserves the intended decimal value, avoiding the precision loss seen with the direct double constructor.

Summary

Because computers store numbers in binary, many decimal fractions cannot be represented exactly, causing double‑based calculations to be approximate.

BigDecimal

overcomes this by storing an unscaled integer and a scale, enabling exact decimal arithmetic. To maintain precision, always create

BigDecimal

objects from

String

values or use

BigDecimal.valueOf

, never from a double directly.

backendJavaPrecisionBigDecimalFloating Point
macrozheng
Written by

macrozheng

Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.