JavaScript数字运算不准确是因为其Number类型基于IEEE 754双精度浮点数,无法精确表示多数十进制小数,如0.1+0.2≠0.3;应对需分场景:金额用整数运算,科学计算用BigInt或decimal.js,显示用Number(toFixed()),比较用误差容忍。

JavaScript 数字运算为什么经常不准?
因为 JavaScript 只有一种数字类型 Number,底层用 IEEE 754 双精度浮点数表示,0.1 + 0.2 !== 0.3 就是典型表现。这不是 bug,而是二进制无法精确表示大多数十进制小数导致的固有局限。
常见精度问题的应对策略
不能一概用 toFixed() 或 Math.round() 修显示——它们返回字符串或四舍五入后丢失原始精度,且对负数、边界值处理不一致。关键看场景:
- 金额计算:必须用整数(单位“分”)运算,避免任何浮点中间步骤
- 科学计算或高精度需求:引入
BigInt(仅整数)或第三方库如decimal.js、big.js - 简单 UI 显示控制:用
Number(val.toFixed(n))转回数字,而非直接用toFixed()结果参与后续计算 - 比较操作:改用误差容忍判断,例如
Math.abs(a - b)
Number.EPSILON 是什么?怎么用?
Number.EPSILON 是 1 与大于 1 的最小可表示数之间的差值(约 2.220446049250313e-16),它不是“通用精度阈值”,只适用于 1 附近的数。比较两个数是否相等,应按数量级缩放误差:
function numbersEqual(a, b) {
if (a === b) return true;
const diff = Math.abs(a - b);
const max = Math.max(Math.abs(a), Math.abs(b), 1);
return diff < Number.EPSILON * max;
}直接写 a === b 对整数安全;对小数比较,别硬套 Number.EPSILON,优先考虑业务容错范围(比如金额允许 ±0.01)。
立即学习“Java免费学习笔记(深入)”;
哪些操作会悄悄引入精度损失?
这些看似无害的操作实际都经过浮点路径:
-
parseFloat('0.1')→ 得到的是近似值,不是精确 0.1 -
JSON.parse('{"price": 19.99}')→ 数字字段仍是浮点表示 -
new Date(2023, 0, 1).getTime() / 1000→ 时间戳除法产生小数秒,精度不可靠 -
0.1 + 0.2 === 0.30000000000000004→ 典型错误链起点
真正可控的方式只有一种:从源头杜绝小数参与运算。比如后端传金额统一为整数分,前端不做 / 100 操作,直到最终渲染才格式化显示。











