JavaScript的Number类型基于IEEE 754双精度浮点标准,存在精度限制:最大安全整数为9007199254740991,超出后整数运算失真;小数如0.1+0.2产生误差;可用Number.isSafeInteger()检测安全整数,小数比较应使用差值阈值。

JavaScript 的 Number 类型基于 IEEE 754 双精度浮点数标准(64 位),这决定了它既能表示很大或很小的数,又存在固有的精度限制——不是所有整数都能被精确表示,超出安全范围后运算结果可能出人意料。
最大值、最小值与安全整数范围
JavaScript 中数值有三个关键边界:
-
最大安全整数:
Number.MAX_SAFE_INTEGER === 9007199254740991(即 2⁵³ − 1)。在此范围内,每个整数都有唯一、精确的 double 表示;超过它,相邻可表示的整数间隔大于 1,导致“跳号”。 -
最小安全整数:
Number.MIN_SAFE_INTEGER === -9007199254740991(即 −(2⁵³ − 1))。 -
最大/最小可表示值:
Number.MAX_VALUE ≈ 1.798e+308,Number.MIN_VALUE ≈ 5e-324(注意:这是最接近 0 的正数,不是负数下界)。
超出 MAX_VALUE 会得到 Infinity;低于 MIN_VALUE(且非零)会变成 0(下溢)。
精度丢失的典型表现
精度问题不只发生在大数,也常见于小数运算:
立即学习“Java免费学习笔记(深入)”;
-
0.1 + 0.2 === 0.30000000000000004—— 因为十进制小数 0.1 和 0.2 在二进制中是无限循环小数,存储时被截断,相加后误差暴露。 -
9007199254740992 + 1 === 9007199254740992—— 超出安全整数范围后,+1 不再改变值。 -
Math.pow(2, 53) + 1 === Math.pow(2, 53)—— 同样因精度粒度变大而“无法感知”+1。
如何检测和规避精度风险
日常开发中可采取以下实用策略:
- 判断是否为安全整数:
Number.isSafeInteger(num),它会同时检查是否为整数且在 ±2⁵³−1 范围内。 - 小数计算避免直接比较:
Math.abs(a - b) 替代 <code>a === b(EPSILON ≈ 2.22e-16是双精度可表示的最小差值)。 - 金融等高精度场景,改用字符串或专用库(如
BigInt处理大整数,decimal.js或big.js处理小数)。 - 序列 ID、时间戳等长整型数据,若来自后端(如 64 位整数),前端应作为字符串接收,避免自动转 Number 后失真。
BigInt:解决大整数精度问题的补充方案
BigInt 是 ES2020 引入的独立类型,用后缀 n 创建(如 123n),可安全表示任意精度整数:
- 支持
+、-、*、**、%等运算,但不能与Number混合运算(会报错)。 -
BigInt(Number.MAX_SAFE_INTEGER) + 1n结果正确;而Number.MAX_SAFE_INTEGER + 1就已不准。 - 注意:
JSON.stringify()不支持BigInt,需手动转换;typeof返回"bigint",不是"number"。
它不替代 Number,而是互补:适合整数计算,不支持小数和 NaN/Infinity。










