Comprehensive Guide to Java BigDecimal: Overview, Constructors, Methods, Formatting, and Common Exceptions
This article provides an in‑depth tutorial on Java's BigDecimal class, covering its purpose for high‑precision arithmetic, common constructors, usage pitfalls, essential methods, number formatting with NumberFormat, handling of division exceptions, and a recommended utility class for precise calculations.
1. Overview of BigDecimal
Java provides the java.math.BigDecimal class for precise arithmetic on numbers with more than 16 significant digits. While double handles up to 16 digits, many applications require higher precision for very large or very small values.
For calculations that do not require exact precision, Float and Double are sufficient, but converting from String to Float/Double loses precision. Therefore, when exact results are needed, BigDecimal should be used.
BigDecimal is an object; arithmetic operators (+, -, *, /) cannot be used directly. Instead, its methods must be called, and all parameters must also be BigDecimal objects. Constructors create instances, especially those with arguments.
2. Common Constructors
2.1 Common Constructors
BigDecimal(int) – creates an instance from an int value.
BigDecimal(double) – creates an instance from a double value.
BigDecimal(long) – creates an instance from a long value.
BigDecimal(String) – creates an instance from a string representation.
2.2 Usage Issues
Example:
BigDecimal a = new BigDecimal(0.1);
System.out.println("a values is:" + a);
System.out.println("=====================");
BigDecimal b = new BigDecimal("0.1");
System.out.println("b values is:" + b);Result:
a values is:0.1000000000000000055511151231257827021181583404541015625
=====================
b values is:0.1Analysis:
The constructor with a double argument yields an unpredictable result because 0.1 cannot be represented exactly as a double, leading to a long binary fraction.
The String constructor is deterministic; new BigDecimal("0.1") equals the expected 0.1, so it is recommended.
If a double must be used as the source, use BigDecimal.valueOf(double) which internally uses Double.toString(double) before constructing.
3. Common Methods
3.1 Basic Operations
add(BigDecimal) – adds and returns a new BigDecimal.
subtract(BigDecimal) – subtracts and returns a new BigDecimal.
multiply(BigDecimal) – multiplies and returns a new BigDecimal.
divide(BigDecimal) – divides and returns a new BigDecimal.
toString() – converts the value to a string.
doubleValue() – converts to double.
floatValue() – converts to float.
longValue() – converts to long.
intValue() – converts to int.
3.2 Comparison
BigDecimal comparison is usually performed with compareTo :
int a = bigDecimal.compareTo(bigDecimal2);Result interpretation: -1 means less, 0 means equal, 1 means greater.
4. Formatting with NumberFormat
NumberFormat.format() can accept a BigDecimal, allowing currency, percent, and general number formatting with more than 16 digits.
Example of formatting currency and percent:
NumberFormat currency = NumberFormat.getCurrencyInstance();
NumberFormat percent = NumberFormat.getPercentInstance();
percent.setMaximumFractionDigits(3);
BigDecimal loanAmount = new BigDecimal("15000.48");
BigDecimal interestRate = new BigDecimal("0.008");
BigDecimal interest = loanAmount.multiply(interestRate);
System.out.println("贷款金额:\t" + currency.format(loanAmount));
System.out.println("利率:\t" + percent.format(interestRate));
System.out.println("利息:\t" + currency.format(interest));Result: 贷款金额: ¥15,000.48 利率: 0.8% 利息: ¥120.00
Formatting method formatToNumber(BigDecimal) keeps two decimal places, pads zeros, and handles values less than 1 by prefixing 0.
public static String formatToNumber(BigDecimal obj) {
DecimalFormat df = new DecimalFormat("#.00");
if (obj.compareTo(BigDecimal.ZERO) == 0) {
return "0.00";
} else if (obj.compareTo(BigDecimal.ZERO) > 0 && obj.compareTo(new BigDecimal(1)) < 0) {
return "0" + df.format(obj).toString();
} else {
return df.format(obj).toString();
}
}Sample output demonstrates various inputs.
5. Common Exceptions
5.1 Division Exception
java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal resultCause: dividing with a non‑terminating decimal without specifying scale.
Solution: use the divide method with a scale, e.g., divide(x, 2) .
6. Summary
6.1 Key Points
Use BigDecimal for precise decimal calculations; it is slower than double/float, so avoid it for low‑precision needs. Prefer the String constructor.
BigDecimal is immutable; each arithmetic operation creates a new instance, so store the result.
6.2 Utility Class Recommendation
package com.vivo.ars.util;
import java.math.BigDecimal;
/**
* Utility for high‑precision arithmetic
*/
public class ArithmeticUtils {
private static final int DEF_DIV_SCALE = 10;
// add, sub, mul, div, round, remainder, compare methods ...
}Architecture Digest
Focusing on Java backend development, covering application architecture from top-tier internet companies (high availability, high performance, high stability), big data, machine learning, Java architecture, and other popular fields.
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.