好,那我给你整理一份 Java BigDecimal 详解,特别针对加、减、乘、除以及小数舍入模式(RoundingMode),带上代码示例 + 注意事项,保证你用起来不踩坑。


1. BigDecimal 作用

  • 主要用于 精确表示和计算小数(金融、金额、精度敏感计算)
  • 不要用 float / double 做精确运算(会有二进制精度误差)
  • BigDecimal 内部用 任意精度的整数 + 小数位数 来存储

2. 创建 BigDecimal(推荐写法)

import java.math.BigDecimal;

public class Demo {
    public static void main(String[] args) {
        // 推荐:用字符串构造,避免精度丢失
        BigDecimal a = new BigDecimal("0.1");
        BigDecimal b = new BigDecimal("0.2");

        System.out.println(a.add(b)); // 0.3
    }
}

❌ 不要用 new BigDecimal(0.1),因为 0.1 作为 double 已经有误差。


3. 加、减、乘、除

import java.math.BigDecimal;
import java.math.RoundingMode;

public class BigDecimalOps {
    public static void main(String[] args) {
        BigDecimal a = new BigDecimal("10.25");
        BigDecimal b = new BigDecimal("3");

        // 加法
        BigDecimal sum = a.add(b); // 13.25

        // 减法
        BigDecimal diff = a.subtract(b); // 7.25

        // 乘法
        BigDecimal product = a.multiply(b); // 30.75

        // 除法(必须指定精度和舍入模式,否则可能抛 ArithmeticException)
        BigDecimal result = a.divide(b, 2, RoundingMode.HALF_UP); // 3.42

        System.out.println("加法: " + sum);
        System.out.println("减法: " + diff);
        System.out.println("乘法: " + product);
        System.out.println("除法: " + result);
    }
}

4. 常用舍入模式(RoundingMode)

模式说明示例(2 位小数)
RoundingMode.UP远离 0 舍入(只要有多余位就进 1)1.234 → 1.24
RoundingMode.DOWN趋向 0 舍入(直接截断)1.239 → 1.23
RoundingMode.CEILING向正无穷大舍入1.231 → 1.24,-1.239 → -1.23
RoundingMode.FLOOR向负无穷大舍入1.239 → 1.23,-1.231 → -1.24
RoundingMode.HALF_UP四舍五入(>=0.5 进 1)1.235 → 1.24
RoundingMode.HALF_DOWN五舍六入(>0.5 进 1)1.235 → 1.23
RoundingMode.HALF_EVEN银行家舍入(0.5 时取偶数)1.225 → 1.22,1.235 → 1.24

5. 常用 API 速查表

a.add(b)                  // 加
a.subtract(b)             // 减
a.multiply(b)             // 乘
a.divide(b, scale, mode)  // 除,指定精度 & 舍入
a.setScale(scale, mode)   // 改变小数位数 & 舍入
a.compareTo(b)            // 比较大小(返回 -1, 0, 1)
a.equals(b)               // 严格相等(值 & 小数位数都相等)
a.stripTrailingZeros()    // 去掉多余的 0
a.toPlainString()         // 以字符串返回,不用科学计数法

6. 实战示例(金额计算)

import java.math.BigDecimal;
import java.math.RoundingMode;

public class MoneyCalc {
    public static void main(String[] args) {
        BigDecimal price = new BigDecimal("19.99");
        BigDecimal quantity = new BigDecimal("3");

        BigDecimal total = price.multiply(quantity); // 59.97
        BigDecimal discount = new BigDecimal("0.15"); // 15% 折扣
        BigDecimal finalPrice = total.multiply(BigDecimal.ONE.subtract(discount))
                                     .setScale(2, RoundingMode.HALF_UP);

        System.out.println("总价: " + total);
        System.out.println("折后价: " + finalPrice);
    }
}

输出:

总价: 59.97
折后价: 50.97

7. 注意事项

  1. 避免使用 double/float 构造 BigDecimal
    • 错误:new BigDecimal(0.1); // 精度有误
    • 正确:new BigDecimal("0.1"); BigDecimal.valueOf(0.1); // 内部转成 String,精度安全
  2. 除法必须指定精度和舍入模式
  3. equals 和 compareTo 区别
    • equals:值 & 小数位都要相等
    • compareTo:只比数值大小