在处理项目金额数据时,虽然 double 日常可用,但无法精确计算金额,BigDecimal 更适合。尽管部分旧项目可能使用 double,但在高精度要求下仍推荐 BigDecimal。
Java 中的 BigDecimal 和 double
1. double
1.1. 无法精确表示部分十进制小数
十进制小数转换为二进制时,部分数值会变成无限循环小数,而 double 只能存储有限位数的二进制,因此会截断并保留近似值。
最经典的例子:
double a = 0.1;
double b = 0.2;
System.out.println(a + b); // 输出 0.30000000000000004(而非预期的 0.3)
原因:0.1 转二进制是 0.0001100110011...(无限循环),double 只能存储其近似值,叠加后误差被放大。
1.2. 能精确表示的情况(特例)
- 整数:在
2^53范围内的整数(约 ±9×10¹⁵),double可以精确存储(例如25、20.0等)。例:25 * 0.8 = 20.0,结果是整数,因此double能精确表示。 - 可被 2 的幂次整除的小数:例如
0.5(二进制0.1)、0.25(二进制0.01)等。
1.3. 适用场景与风险场景
适合使用 double 的场景
- 科学计算 / 工程计算:允许微小误差(如物理模型、图形渲染、数据统计等)。
- 非精确小数场景:如温度(
23.5℃)、体重(62.3kg)等,对精度要求不高的数值。 - 需要大范围数值:当数值范围超过整数类型(如
long的上限 ±9×10¹⁸),且可接受近似值时。
禁止使用 double 的场景(精度敏感)
- 金融 / 支付相关:金额(如
100.05元)、税率、手续费等,误差可能导致资金损失或对账不平。 - 业务关键小数:如商品单价、折扣率、库存数量(带小数,如
1.5件)等,需精确记录和计算。 - 数据库字段映射:若数据库用
NUMERIC/DECIMAL(精确小数类型),实体类用double接收会导致精度丢失。


