javascript浮点数精度丢失无法完全避免,可通过整数放大法、decimal.js/bignumber.js、安全格式化及bigint等方法控制误差。

JavaScript 中浮点数精度丢失无法完全避免,但可以通过合适的方法控制误差、保证业务结果正确。核心思路是:绕开二进制浮点运算的固有缺陷,改用整数、字符串或专用高精度类型来处理关键数值。
用整数放大法做加减乘除
适用于金额、价格等小数位数固定(如两位)的场景。把所有数字转成整数计算,最后再还原小数点位置。
- 先统计参与运算的数中小数位最多几位,比如 0.123 和 4.5,最多是 3 位,放大倍数就是 10³ = 1000
- 计算:
Math.round(0.123 * 1000) + Math.round(4.5 * 1000) === 123 + 4500 === 4623 - 还原:
4623 / 1000 === 4.623
注意要用 Math.round 而非直接乘,防止放大时引入新误差;但也要警惕放大后超出 Number.MAX_SAFE_INTEGER(约 9e15),否则整数本身也会失真。
引入 decimal.js 或 bignumber.js
需要高可靠性的金融、科学计算时,这是最稳妥的选择。它们用字符串+算法模拟十进制运算,不依赖原生 Number。
-
decimal.js 更轻量,API 清晰,支持四舍五入模式、精度设置(如
new Decimal('0.1').plus('0.2').toFixed(1)) - bignumber.js 功能全面,兼容性好,对链式调用和大数支持更成熟
二者都不受 IEEE 754 限制,能精确表示 0.1 + 0.2 === 0.3,也支持 1.335.toFixed(2) === '1.34' 这类正确四舍五入。
对展示结果做安全格式化
如果只是前端显示(比如金额、百分比),不需要参与后续计算,可用 toFixed + parseFloat 组合兜底。
- 例如:
parseFloat((0.1 + 0.2).toFixed(10))→0.3 - 注意:
toFixed返回字符串,且对1.005等边界值仍可能异常(因底层仍是浮点数),所以仅限展示,不可用于中间计算
推荐搭配 Intl.NumberFormat 做国际化格式输出,它内部做了精度保护,更健壮。
大整数用 BigInt 避免安全整数溢出
当处理 ID、时间戳、加密数值等超大整数(> 2⁵³−1)时,Number 类型会自动“合并”相邻整数,导致 9007199254740992 === 9007199254740993 为 true。
- 用
BigInt('9007199254740992')显式声明,所有运算都保持精确 - 注意:
BigInt不能和Number混用(如1n + 2报错),需统一类型 - 适合纯整数场景,不支持小数,也不参与浮点运算
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











