Comprehensive Guide to Java BigDecimal: Overview, Constructors, Common Methods, Formatting, and Exceptions
This article provides an in‑depth overview of Java's BigDecimal class, covering its purpose for high‑precision arithmetic, frequently used constructors, essential methods for arithmetic and conversion, techniques for formatting numbers, handling of common exceptions, and includes practical code examples and a utility class for precise calculations.
1 BigDecimal Overview
Java's java.math.BigDecimal class is provided for precise calculations on numbers that exceed 16 significant digits. While the double primitive can handle up to 16 digits, many real‑world scenarios require higher precision.
For calculations where exact precision is not required, Float and Double are sufficient, but using Double.valueOf(String) or Float.valueOf(String) can lose precision. Therefore, when exact results are needed, BigDecimal must be used.
BigDecimal objects cannot be operated on with the traditional arithmetic operators + - * / ; instead, you must call the corresponding methods, and the method arguments must also be BigDecimal instances.
2 Common Constructors
2.1 Frequently Used Constructors
BigDecimal(int) – creates an object with the specified integer value.
BigDecimal(double) – creates an object with the specified double value.
BigDecimal(long) – creates an object with the specified long value.
BigDecimal(String) – creates an object with the value represented by the given string.
2.2 Usage Analysis
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 that takes a double can produce an unpredictable result because 0.1 cannot be represented exactly as a double. The created BigDecimal actually equals 0.1000000000000000055511151231257827021181583404541015625 .
The String constructor is fully predictable; new BigDecimal("0.1") creates a BigDecimal that exactly equals 0.1. Therefore, the String constructor is generally recommended.
If a double must be used as the source, use BigDecimal.valueOf(double) which internally converts the double via Double.toString(double) before constructing the BigDecimal.
3 Common Methods Detail
3.1 Frequently Used Methods
add(BigDecimal) – adds the value of another BigDecimal and returns a new BigDecimal.
subtract(BigDecimal) – subtracts the value of another BigDecimal and returns a new BigDecimal.
multiply(BigDecimal) – multiplies by another BigDecimal and returns a new BigDecimal.
divide(BigDecimal) – divides by another BigDecimal and returns a new BigDecimal.
toString() – converts the BigDecimal to its string representation.
doubleValue() – converts the BigDecimal to a double.
floatValue() – converts the BigDecimal to a float.
longValue() – converts the BigDecimal to a long.
intValue() – converts the BigDecimal to an int.
3.2 Size Comparison
BigDecimal comparison is usually performed with the compareTo method.
int a = bigDecimal.compareTo(bigDecimal2);Result interpretation:
a = -1 → first number is smaller.
a = 0 → numbers are equal.
a = 1 → first number is larger.
4 Formatting
The NumberFormat.format() method can accept a BigDecimal, allowing currency, percent, and general number formatting.
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.00Formatting to keep two decimal places (padding with zeros if necessary):
public class NumberFormat {
public static void main(String[] s) {
System.out.println(formatToNumber(new BigDecimal("3.435")));
System.out.println(formatToNumber(new BigDecimal("0")));
System.out.println(formatToNumber(new BigDecimal("0.00")));
System.out.println(formatToNumber(new BigDecimal("0.001")));
System.out.println(formatToNumber(new BigDecimal("0.006")));
System.out.println(formatToNumber(new BigDecimal("0.206")));
}
/**
* @desc 1.0~1 between BigDecimal, if leading zero is lost after formatting, prepend 0.
* 2. If the argument equals 0, return "0.00".
* 3. For numbers greater than 1, format directly.
*/
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();
}
}
}Result:
3.44
0.00
0.00
0.00
0.01
0.215 Common Exceptions
5.1 Exceptions During Division
java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal resultCause: When BigDecimal.divide() encounters a non‑terminating decimal (infinite repeating fraction) without a specified scale, it throws this exception.
Solution: Specify a scale in the divide method, e.g., divide(divisor, 2) , to define the number of decimal places.
6 Summary
6.1 Key Points
Use BigDecimal only when precise decimal calculation is required; it is slower than double/float, especially for large or complex operations.
Prefer the String constructor to avoid precision loss.
BigDecimal is immutable; each arithmetic operation creates a new object, so store the result.
6.2 Utility Class Recommendation
package com.vivo.ars.util;
import java.math.BigDecimal;
/**
* Utility class for high‑precision arithmetic operations.
*/
public class ArithmeticUtils {
private static final int DEF_DIV_SCALE = 10;
public static double add(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.add(b2).doubleValue();
}
public static BigDecimal add(String v1, String v2) {
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.add(b2);
}
public static String add(String v1, String v2, int scale) {
if (scale < 0) throw new IllegalArgumentException("The scale must be a positive integer or zero");
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.add(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
}
// Similar methods for sub, mul, div, round, remainder, compare, etc.
}Selected Java Interview Questions
A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!
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.