核心原因:IEEE 754 双精度浮点数格式
JavaScript 使用 IEEE 754 标准中的 64 位双精度浮点数。这种格式将一个数字分为三部分:
位数 | 部分 | 描述 |
---|---|---|
1 | 符号位 | 表示正负号(0=正,1=负) |
11 | 指数位 | 表示数值的规模(经过偏移编码) |
52 | 尾数/有效位 | 表示实际的数字精度部分(隐含1) |
表达方式
公式含义
- (-1)^s:决定正负
- s = 0 ⇒ (-1)^0 = +1(正数)
- s = 1 ⇒ (-1)^1 = -1(负数
- 1.f:有效数字
- 尾数 f 是一个 52 位的二进制小数。
- IEEE 754 会自动在前面加一个“1.” ⇒ 称为隐含的 1
- 所以实际有效数字是 1.f,精度为 53 位(二进制)
- 2^(e - 1023):指数部分
- e 是一个 11 位无符号整数(0~2047) 它使用 偏移值 1023(bias)
- 实际指数 = e - 1023
- 如果 e = 1023 ⇒ 实际指数 = 0 ⇒ 没有缩放
- 如果 e = 1026 ⇒ 实际指数 = 3 ⇒ 放大2^3
示例
1 | 6.5 = 110.1(二进制) = 1.101 × 2^2 |
结论
0.1 和 0.2 在二进制中都是一个无限循环的小数 所有相加时会出现
0.1 + 0.2 = 0.30000000000000004(近似) 而不是期望的 0.3