Why Does BigDecimal Preserve Exact Precision in Monetary Calculations?
The article explains how Java's BigDecimal class avoids precision loss by scaling numbers into integer representations, detailing its internal fields, the add method's branching logic, and a concrete test that demonstrates exact decimal addition for financial values.
BigDecimal is the preferred type for monetary calculations in Java because it guarantees that no decimal precision is lost. The article starts by stating this common practice and then dives into the class definition to show the fields that enable precise arithmetic.
The class declaration is:
public class BigDecimal extends Number implements Comparable<BigDecimal> {
private final BigInteger intVal; // unscaled integer value
private final int scale; // number of digits after the decimal point
private transient int precision; // reserved, usually 0
private transient String stringCache; // cached canonical string
private final transient long intCompact; // compact long representation when possible
}A simple JUnit test demonstrates the behavior:
@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); // prints 5.86
}Debugging after the two valueOf calls shows the fields being populated with the unscaled values (236 and 35) and their respective scales (2 and 1).
The add instance method first chooses an overload based on whether the operands have a compact long representation. It eventually delegates to the static method add(long xs, int scale1, long ys, int scale2), where the core scaling logic resides.
Inside that static method, the difference between the two scales ( sdiff = scale1 - scale2) determines the path:
If the scales are equal, the two long values are added directly.
If sdiff < 0, the first operand is scaled up by a power of ten (using checkScale and longMultiplyPowerTen) so that both operands share the larger scale.
If sdiff > 0, the second operand is scaled similarly.
After scaling, the method calls another overload add(long xs, long ys, int scale) which computes the sum of the two long values. If the sum fits in a long, it returns BigDecimal.valueOf(sum, scale); otherwise it constructs a BigDecimal from a BigInteger to hold the larger result.
Because the arithmetic is performed on integer values (either long or BigInteger) and the original decimal position is recorded in the scale field, the calculation never suffers from binary floating‑point rounding errors. The final object restores the decimal point using the stored scale, delivering an exact result such as 5.86.
Thus, BigDecimal preserves precision by converting decimal numbers to scaled integers, performing pure integer arithmetic, and then re‑applying the scale to produce the correct decimal representation.
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.
Programmer XiaoFu
xiaofucode.com – a programmer learning guide driven by the pursuit of profit
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.
