JavaScript 的 Number 类型基于 IEEE 754 双精度浮点数标准,能精确表示的安全整数范围为 ±(2⁵³−1),超出则精度丢失;小数如 0.1 因二进制无限循环被截断,导致 0.1+0.2≠0.3;应通过整数运算或误差容忍比较规避问题。

JavaScript 中的 Number 类型基于 IEEE 754 双精度浮点数标准(64 位),其能精确表示的整数范围有限,超出该范围后就会发生精度丢失。这不是 JavaScript 的 Bug,而是浮点数在二进制下表示十进制小数时的固有数学限制。
IEEE 754 双精度数的结构
一个 Number 占用 64 位,分为三部分:
- 1 位符号位(S):决定正负;
- 11 位指数位(E):表示数量级,偏移量为 1023;
- 52 位尾数位(M):存储有效数字(实际精度为 53 位,因隐含前导 1)。
因此,任意可精确表示的数都形如:
(−1)S × (1 + M / 252) × 2E−1023
其中 M ∈ [0, 252) 是整数。这意味着所有能被精确表示的数,必须能写成该形式——而大多数十进制小数(如 0.1)无法用有限位二进制小数表达,于是被截断或舍入,造成误差。
安全整数范围:253 − 1
当指数 E 固定为使数值为整数时,尾数 M 最多提供 53 位二进制有效位(含隐含 1)。因此,能被唯一、精确表示的最大连续整数是:
- Number.MAX_SAFE_INTEGER = 253 − 1 = 9,007,199,254,740,991;
- 超过此值,相邻可表示数的间隔 ≥ 2,导致整数“跳变”(例如
2<sup>53</sup> + 1 === 2<sup>53</sup>); - 小于等于该值的整数,只要不涉及浮点运算中间过程,都能无损存储和比较。
小数精度丢失的典型表现
十进制小数转二进制时若为无限循环小数(如 0.1),就必须截断到 53 位有效位:
立即学习“Java免费学习笔记(深入)”;
-
0.1在二进制中是循环小数0.0001100110011…<sub>2</sub>,无法精确终止; - JavaScript 实际存储的是最接近它的双精度近似值,约为
0.1000000000000000055511151231257827021181583404541015625; - 因此
0.1 + 0.2 !== 0.3,因为左右两边都是各自近似值相加的结果,误差累积后不再相等。
避免精度问题的实用原则
关键不是“修复”浮点数,而是适配其数学本质:
- 对金额等高精度场景,用整数单位(如“分”)代替小数(如“元”);
- 比较浮点数时,不用
===,而用误差容忍(如Math.abs(a - b) ); - 需要精确小数运算时,使用
BigInt(仅整数)或第三方库(如decimal.js); - 理解
parseInt("0.0000001") → 0或parseFloat("1.0000000000000001") → 1是舍入行为,非解析错误。


















