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.

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

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:

BigDecimal recommend1 = new BigDecimal("0.1");
BigDecimal recommend2 = BigDecimal.valueOf(0.1);

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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

precisionBigDecimalfloating-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

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.