Fundamentals 7 min read

Why BigDecimal Guarantees Exact Precision in Java Calculations

This article explains how Java's BigDecimal class preserves decimal precision by scaling numbers to long integers, detailing its internal fields, key methods, and step‑by‑step execution of an addition example to illustrate the underlying algorithm.

Java Backend Technology
Java Backend Technology
Java Backend Technology
Why BigDecimal Guarantees Exact Precision in Java Calculations

Class Introduction

Java's BigDecimal class extends Number and implements Comparable<BigDecimal>. Its core fields are:

public class BigDecimal extends Number implements Comparable<BigDecimal> {
    // Unscaled value
    private final BigInteger intVal;
    // Scale (number of digits after the decimal point)
    private final int scale;
    // Cached precision (unused, default 0)
    private transient int precision;
    // Cached string representation
    private transient String stringCache;
    // Compact long representation
    private final transient long intCompact;
}

Example Walkthrough

A JUnit test demonstrates addition:

@Test
public void testBigDecimal() {
    BigDecimal bigDecimal1 = BigDecimal.valueOf(2.36);
    BigDecimal bigDecimal2 = BigDecimal.valueOf(3.5);
    BigDecimal resDecimal = bigDecimal1.add(bigDecimal2);
    System.out.println(resDecimal);
}

After calling BigDecimal.valueOf(2.36), the debugger shows the fields being populated.

The add method is then examined:

/**
 * Returns a BigDecimal whose value is (this + augend),
 * and whose scale is max(this.scale(), augend.scale()).
 */
public BigDecimal add(BigDecimal augend) {
    if (this.intCompact != INFLATED) {
        if (augend.intCompact != INFLATED) {
            return add(this.intCompact, this.scale, augend.intCompact, augend.scale);
        } else {
            return add(this.intCompact, this.scale, augend.intVal, augend.scale);
        }
    } else {
        if (augend.intCompact != INFLATED) {
            return add(augend.intCompact, augend.scale, this.intVal, this.scale);
        } else {
            return add(this.intVal, this.scale, augend.intVal, augend.scale);
        }
    }
}

For the example, the parameters are xs=236, scale1=2, ys=35, scale2=1. The method first computes the scale difference ( sdiff = scale1 - scale2 = 1) and follows the branch where sdiff < 0 is false, so it executes the final else block.

private static BigDecimal add(final long xs, int scale1, final long ys, int scale2) {
    long sdiff = (long) scale1 - scale2;
    if (sdiff == 0) {
        return add(xs, ys, scale1);
    } else if (sdiff < 0) {
        int raise = checkScale(xs, -sdiff);
        long scaledX = longMultiplyPowerTen(xs, raise);
        if (scaledX != INFLATED) {
            return add(scaledX, ys, scale2);
        } else {
            BigInteger bigsum = bigMultiplyPowerTen(xs, raise).add(ys);
            return ((xs^ys) >= 0) ? new BigDecimal(bigsum, INFLATED, scale2, 0)
                                 : valueOf(bigsum, scale2, 0);
        }
    } else {
        int raise = checkScale(ys, sdiff);
        long scaledY = longMultiplyPowerTen(ys, raise);
        if (scaledY != INFLATED) {
            return add(xs, scaledY, scale1);
        } else {
            BigInteger bigsum = bigMultiplyPowerTen(ys, raise).add(xs);
            return ((xs^ys) >= 0) ? new BigDecimal(bigsum, INFLATED, scale1, 0)
                                 : valueOf(bigsum, scale1, 0);
        }
    }
}

Since sdiff = 1, the method scales ys by 10 (raising it to 350) and then calls the three‑argument add:

private static BigDecimal add(long xs, long ys, int scale) {
    long sum = add(xs, ys);
    if (sum != INFLATED)
        return BigDecimal.valueOf(sum, scale);
    return new BigDecimal(BigInteger.valueOf(xs).add(ys), scale);
}

This final step computes the sum as a long integer and constructs a new BigDecimal with the appropriate scale, ensuring no precision loss.

Conclusion

BigDecimal achieves exact precision by converting decimal numbers into scaled long integers (or BigInteger when overflow occurs), performing integer arithmetic, and then applying the stored scale to produce the final result.

Source: https://juejin.cn/post/7348709938023940136
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.

BackendprecisionArithmeticBigDecimalnumber
Java Backend Technology
Written by

Java Backend Technology

Focus on Java-related technologies: SSM, Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading. Occasionally cover DevOps tools like Jenkins, Nexus, Docker, and ELK. Also share technical insights from time to time, committed to Java full-stack development!

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.