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.
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.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
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.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
