java浮点数精度丢失是ieee 754标准固有特性,非bug;应避免用float/double做金额、唯一标识、阈值判断等精确计算,改用bigdecimal或整数单位(如“分”)处理。

Java 中浮点型数据类型(float 和 double)的精度丢失不是 bug,而是 IEEE 754 标准下的固有特性:十进制小数(如 0.1)在二进制中往往无限循环,而 float(23 位尾数)和 double(52 位尾数)只能截断存储,导致舍入误差。
解决的关键不在于“修复浮点数”,而在于按场景选对工具、写对逻辑。
避免用 float/double 做精确计算
以下业务必须禁用浮点类型直接运算:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 金额计算(如 19.99 元 + 0.5 元手续费)
- 身份编号、订单号、数据库主键等唯一标识
- 需要严格相等判断的阈值(如 if (rate == 0.95))
- 累计类逻辑(如库存扣减、积分累加)
优先使用 BigDecimal 处理精确小数
它用字符串构造、十进制运算,无二进制转换误差:
- ✅ 正确方式:
new BigDecimal("0.1")或BigDecimal.valueOf(1, 1) - ❌ 错误方式:
new BigDecimal(0.1)—— 传入的 double 本身已失真 - 运算用
add()、subtract()、multiply()、divide()(注意指定MathContext或保留小数位) - 输出时用
toPlainString()避免科学计数法,如new BigDecimal("123.456").toPlainString()→ "123.456"
用整数单位替代小数(尤其金额)
把“元”转为“分”,全程用 long 或 int 运算:
- 19.99 元 → 存为
1999(单位:分) - 加减乘除都无精度问题,最后展示时再除以 100.0 并格式化
- 适合高频、简单、确定位数的场景(如电商支付、账单汇总)
浮点数比较与迭代要绕开陷阱
不依赖绝对相等,也不用浮点数当循环变量:
- 比较两个
double是否“相等”:Math.abs(a - b) - 避免
for (double x = 0.0; x —— 改成 <code>for (int i = 0; i - 图形、传感器、模型权重等容忍误差的场景,可继续用
float/double,但不用于判定或累计
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










