JavaScript数值处理严格遵循IEEE 754双精度标准,64位中52位尾数决定精度上限,导致安全整数极限为2⁵³−1(9007199254740991),小数精度丢失源于十进制与二进制转换限制,引擎不提供自动高精度fallback。

JavaScript 引擎内部对数值的处理完全遵循 IEEE 754 双精度浮点数标准(64 位),这不是某家引擎的“设计选择”,而是语言规范强制要求的行为。所有主流引擎(V8、SpiderMonkey、JavaScriptCore)都严格按此实现,因此精度限制是统一且不可绕过的底层约束。
核心存储结构决定精度上限
一个 Number 在内存中固定占用 64 位,拆分为三部分:
- 1 位符号位:决定正负
- 11 位指数位:决定数量级范围(可表示约 ±10³⁰⁸)
- 52 位尾数位(有效数字位):这是精度瓶颈所在——它实际提供最多 53 位二进制精度(隐含首位 1)
这意味着:能被精确表示的十进制整数,必须满足其二进制形式能在 53 位内完整表达。超出后,相邻可表示数之间的间隔不再为 1,而是 ≥ 2,导致“跳号”。
安全整数边界不是经验阈值,而是数学必然
Number.MAX_SAFE_INTEGER === 2<sup>53</sup> − 1(即 9007199254740991)不是近似值,而是由 53 位精度直接推导出的理论极限:
立即学习“Java免费学习笔记(深入)”;
- 从 0 到 253−1 的每个整数,都有唯一、无歧义的 double 表示;
- 253 开始,精度粒度变为 2,所以
9007199254740992 === 9007199254740993返回 true; - 该限制适用于所有整数运算,包括
++、+、数组索引、Date.getTime()等场景。
小数精度丢失本质是进制转换失败
十进制小数能否精确表示,取决于它是否能写成 k / 2<sup>n</sup>(k、n 为整数)。例如:
- 0.5 = 1/2 → 可精确表示;
- 0.75 = 3/4 = 1/2 + 1/4 → 可精确表示;
- 0.1 = 1/10 → 分母含因子 5,无法写成纯 2 的幂分母 → 二进制无限循环 → 截断后存入 52 位尾数 → 必然误差。
这种误差在加减乘除中会传播和放大,不是“计算错误”,而是存储阶段就已固化。
引擎不提供“更高精度”的原生 fallback
V8 等引擎不会自动降级或切换表示方式。一旦数值超出安全整数范围或涉及非 2⁻ⁿ 小数,引擎仍照常运算,但结果就是 IEEE 754 定义下的“正确错误值”。比如:
-
0.1 + 0.2得到0.30000000000000004,这是标准规定的最接近真实和的 double 值; -
Math.pow(2, 53) + 1返回9007199254740992,因为该值在 double 中无法与原值区分。
引擎不做额外校验或告警——这是性能与规范一致性的取舍。


















