在Java开发中,浮点数运算的精度丢失是开发者经常遇到的问题,使用double或float类型处理金额、统计类数值时,很容易出现计算结果不符合预期的情况,而BigDecimal类就是专门用来解决这类高精度数值处理需求的工具。

BigDecimal的创建方式
创建BigDecimal对象时,不建议直接使用构造方法传入double类型参数,因为double本身存在精度问题,会导致创建出来的BigDecimal对象数值不准确。推荐的创建方式有以下两种:
1. 使用字符串构造方法
这是最安全的创建方式,能够完全保留数值的原始精度:
import java.math.BigDecimal;
public class BigDecimalDemo {
public static void main(String[] args) {
// 使用字符串构造,精度不会丢失
BigDecimal num1 = new BigDecimal("123.456");
BigDecimal num2 = new BigDecimal("0.01");
System.out.println("num1的值:" + num1);
System.out.println("num2的值:" + num2);
}
}2. 使用valueOf方法
BigDecimal的valueOf方法内部会先将double转换为字符串再构造对象,同样可以避免精度问题:
import java.math.BigDecimal;
public class BigDecimalDemo {
public static void main(String[] args) {
// 使用valueOf方法,内部处理了精度问题
BigDecimal num1 = BigDecimal.valueOf(123.456);
BigDecimal num2 = BigDecimal.valueOf(0.01);
System.out.println("num1的值:" + num1);
System.out.println("num2的值:" + num2);
}
}BigDecimal的常用运算方法
BigDecimal提供了对应的方法来实现加减乘除等常见运算,注意这些运算方法都不会修改原对象,而是返回一个新的BigDecimal对象:
add(BigDecimal augend):加法运算subtract(BigDecimal subtrahend):减法运算multiply(BigDecimal multiplicand):乘法运算divide(BigDecimal divisor, int scale, RoundingMode roundingMode):除法运算,需要指定保留小数位数和舍入模式
以下是运算的示例代码:
import java.math.BigDecimal;
import java.math.RoundingMode;
public class BigDecimalCalcDemo {
public static void main(String[] args) {
BigDecimal a = new BigDecimal("10.5");
BigDecimal b = new BigDecimal("3.2");
// 加法
BigDecimal addResult = a.add(b);
System.out.println("加法结果:" + addResult);
// 减法
BigDecimal subResult = a.subtract(b);
System.out.println("减法结果:" + subResult);
// 乘法
BigDecimal mulResult = a.multiply(b);
System.out.println("乘法结果:" + mulResult);
// 除法,保留2位小数,四舍五入
BigDecimal divResult = a.divide(b, 2, RoundingMode.HALF_UP);
System.out.println("除法结果(保留2位小数):" + divResult);
}
}精度与舍入模式控制
除法运算时必须指定小数位数和舍入模式,否则如果遇到除不尽的情况会直接抛出ArithmeticException异常。常见的舍入模式有以下几种:
| 舍入模式 | 说明 |
|---|---|
| RoundingMode.HALF_UP | 四舍五入,最常用的舍入模式 |
| RoundingMode.HALF_DOWN | 五舍六入 |
| RoundingMode.HALF_EVEN | 向最接近的数字舍入,如果距离相等则向相邻的偶数舍入 |
| RoundingMode.DOWN | 直接截断,不进位 |
| RoundingMode.UP | 只要有小数位就进位 |
如果需要调整已有BigDecimal对象的小数位数,可以使用setScale方法:
import java.math.BigDecimal;
import java.math.RoundingMode;
public class BigDecimalScaleDemo {
public static void main(String[] args) {
BigDecimal num = new BigDecimal("123.4567");
// 保留2位小数,四舍五入
BigDecimal scaledNum = num.setScale(2, RoundingMode.HALF_UP);
System.out.println("调整后的值:" + scaledNum);
}
}使用注意事项
不要在构造BigDecimal时直接传入double类型参数,例如new BigDecimal(0.1)得到的实际值并不是0.1,而是0.1000000000000000055511151231257827021181583404541015625,会引入精度问题。另外,BigDecimal对象的大小比较不要使用equals方法,因为equals方法会比较数值和精度,例如new BigDecimal("1.0").equals(new BigDecimal("1"))会返回false。如果需要比较数值大小,应该使用compareTo方法:
import java.math.BigDecimal;
public class BigDecimalCompareDemo {
public static void main(String[] args) {
BigDecimal num1 = new BigDecimal("1.0");
BigDecimal num2 = new BigDecimal("1");
// 比较数值大小,返回-1表示小于,0表示等于,1表示大于
int result = num1.compareTo(num2);
System.out.println("比较结果(0表示相等):" + result);
}
}
BigDecimalJava高精度计算数值精度修改时间:2026-06-06 06:31:47