javascript number 类型因 ieee 754 二进制存储无法精确表示十进制小数,解决需绕过缺陷:1. 整数放大法(如金额);2. 高精度库(如 decimal.js 传字符串);3. 大整数用字符串+bigint;4. 浮点比较用容差。

JavaScript 的 Number 类型基于 IEEE 754 双精度浮点数标准,天生无法精确表示很多十进制小数(比如 0.1),导致加减乘除结果出现微小误差(如 0.1 + 0.2 === 0.30000000000000004)。这不是 bug,而是二进制存储机制的固有限制。解决的关键不是“修复”Number,而是绕过它的缺陷,用更可控的方式处理关键数值。
整数放大法(适合金额、固定小数位场景)
把小数转成整数运算,算完再缩放回原单位。适用于价格、百分比等小数位数确定(如两位)的业务。
- 先确定所有参与运算的数中最多几位小数,例如
19.99和0.005最多是 3 位,放大倍数就是1000 - 用
Math.round(num * factor)转整数(不能直接乘,避免放大过程引入新误差) - 整数间完成加减乘除,最后除以相同倍数还原
- 注意:放大后结果不能超过
Number.MAX_SAFE_INTEGER(约9e15),否则整数本身也会失真
引入高精度计算库(推荐用于金融、科学计算)
用字符串+自定义算法模拟十进制运算,彻底脱离原生 Number 的二进制限制。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
decimal.js:轻量、API 清晰、支持四舍五入模式和动态精度控制,例如
new Decimal('0.1').plus('0.2').toFixed(1) - bignumber.js:功能全面,支持更多数学函数,适合复杂运算场景
- 务必传入字符串字面量(如
'0.1'),避免从原始Number初始化,否则误差已在输入时产生
大整数安全处理(应对 ID、时间戳等超范围整数)
当后端返回的 long 型 ID 或大时间戳超过 9007199254740991 时,Number 已无法准确表示,会出现如 9007199254740992 === 9007199254740993 这类错误。
- 后端序列化时将 long 字段转为字符串(Spring 中可用
@JsonSerialize(using = ToStringSerializer.class)) - 前端接收后保持字符串形式展示或传递,仅在必要时用
BigInt进行计算(注意BigInt不能与Number混用) - 避免直接
JSON.parse后对大数字做算术运算,这是最常见的精度丢失入口
容错比较与显示优化(辅助手段,不替代核心方案)
在不需要精确计算、只做展示或简单判断的场合,可降低对精度的依赖。
- 比较两个浮点数是否“相等”时,用
Math.abs(a - b) 替代 <code>=== - 展示时用
.toFixed(n)或.toLocaleString()格式化,但注意它返回字符串,且toFixed在某些边界值上不严格四舍五入 - 避免连续浮点运算链,能合并的步骤尽量合并,减少误差累积机会
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










