bigdecimal构造禁用double字面量,应使用字符串如new bigdecimal("0.1");运算须调用add、subtract等方法;除法必须指定scale和roundingmode;比较用compareto而非equals;慎用避免性能损耗。

BigDecimal构造时别用double字面量
直接用new BigDecimal(0.1)会导致精度污染,因为0.1这个double字面量在二进制中本就是近似值,传进去就已失真。
- 正确做法:用字符串构造,比如
new BigDecimal("0.1") - 错误现象:
new BigDecimal(0.1).toString()返回"0.1000000000000000055511151231257827021181583404541015625" - 如果已有
double变量且无法改源头,先转String.valueOf(d)再构造,但要意识到这仍可能暴露原始double的舍入误差
运算必须用方法调用,不能用+−×÷操作符
Java不支持BigDecimal重载运算符,写a + b实际是String拼接或编译报错,根本不是计算。
- 加法用
a.add(b),减法用a.subtract(b),乘法用a.multiply(b),除法必须指定scale和RoundingMode,如a.divide(b, 2, RoundingMode.HALF_UP) - 除法最容易踩坑:不指定
scale和舍入模式会抛ArithmeticException(如1.divide(3)无限循环小数) -
compareTo()比较大小,别用==或equals()——后者会比较scale,new BigDecimal("1.0").equals(new BigDecimal("1"))返回false
setScale()和divide()里的RoundingMode选哪个?
舍入模式决定如何处理多余位数,选错会导致业务逻辑偏差,比如财务四舍五入必须用RoundingMode.HALF_UP,而非默认的RoundingMode.UNNECESSARY(要求整除)。
-
RoundingMode.HALF_UP:最常用,类似数学四舍五入(1.5 → 2,-1.5 → -2) -
RoundingMode.HALF_EVEN:银行家舍入,减少统计偏差,适合大量数据聚合 -
RoundingMode.CEILING和FLOOR用于向上/向下取整,注意负数行为(-1.1 CEILING → -1,FLOOR → -2) - 所有涉及缩放的操作(包括
divide、setScale)都必须显式声明RoundingMode,JDK 8+不接受int风格的舍入常量
性能与内存开销比double高不少,别滥用
BigDecimal是对象,每次运算都新建实例,堆内存占用大,GC压力明显,纯计数或非金融场景没必要上。
立即学习“Java免费学习笔记(深入)”;
- 高频循环里反复创建
BigDecimal(比如日志统计、实时指标聚合)会显著拖慢吞吐 - 如果只是做“是否相等”判断且输入确定为整数,
long或BigInteger更轻量 - 数据库字段对应
DECIMAL类型时,ORM(如MyBatis)通常自动映射为BigDecimal,这时用它没问题;但中间计算若可预估范围,考虑先转long(单位转为“分”)再算
真正要小心的是隐式类型转换——比如从double参数一路流进BigDecimal构造,表面用了高精度类,实则起点就错了。










