浮点数精度丢失是二进制表示的天然限制,应按需控制:金额等场景用整数运算(如“元”转“分”),科学计算用高精度十进制类型(如bigdecimal、decimal.js),比较时用误差范围而非==。

浮点数精度丢失不是 bug,而是二进制表示小数的天然限制。关键不在于“完全避免”,而在于“按需控制”——该精确的地方必须精确,可容忍误差的地方不必过度防御。
用整数代替小数参与运算
适用于金额、计数、配置值等对精度敏感的场景。核心思路是把“元”转成“分”,“米”转成“毫米”,让所有计算都在整数域完成。
- Java 中:金额统一存为 long 类型的“分”,如 19.99 元 → 1999 分
- JavaScript 中:0.1 + 0.2 可改写为 (10 + 20) / 100 = 0.3,先乘 10 的幂转整数,算完再除回去
- 注意:直接
0.14 * 100可能得14.000000000000002,建议配合Math.round()或字符串解析获取真实小数位数
使用高精度十进制类型
当业务逻辑天然含小数(如利率、税率、科学测量),且需多次参与运算或比较时,应切换到真正按十进制存储的类型。
- Java:用 BigDecimal,构造时传字符串(
new BigDecimal("0.1")),避免new BigDecimal(0.1)继承 double 的误差 - JavaScript:用 decimal.js 或 bignumber.js,支持链式调用和精度控制,如
new BigNumber(0.1).plus(0.2).toNumber() - Python:用 decimal.Decimal,默认精度 28 位,可显式设置上下文
改掉“相等判断”习惯
float/double 不适合做 == 或 != 判断,尤其在条件分支、循环终止、断言中。
- 正确做法:用误差范围(epsilon)比较,如
Math.abs(a - b) - 区分用途:若用于图形渲染或传感器归一化,
1e-5足够;若用于金融阈值判断,应先转整数或 BigDecimal 再比 - 警惕
/ <code>>:比如判别式 Δ
识别哪些场景可以放心用 float/double
不是所有地方都要“大动干戈”。理解边界,才能合理分配开发成本。
- 图形渲染、音视频编解码、机器学习训练:硬件加速依赖 float,且人眼/人耳对微小误差不敏感
- 传感器原始数据(GPS 坐标、加速度计读数):设备本身误差远大于浮点表示误差,无需额外处理
- 相对比例计算(如 alpha = 0.7f、归一化向量长度):只要结果在合理范围内波动,不影响最终视觉或物理表现










