- 为何 0.1 + 0.2 !== 0.3?
- 为何 Number.MAX_SAFE_INTEGER 值为 Math.pow(2, 53) - 1?
- 为何 Math.pow(2, 53) === Math.pow(2, 53) + 1 ?
- 为何 Number.MAX_VALUE = 1.7976931348623157e+308 ?
- 为何 1.005.toFixed(2) = 1.00 ?
下图是单精度格式 git
为何E(双精度)范围是:-1022 ~ 1023 ?github
// E 的范围
E = 0 二进制表示: 0 1111 1111 11 => 2^10 -1 = 1023
E 最大二进制表示(不能全为1):1 1111 1111 10 => 2^11 - 2 = 2046
E 最小二进制表示(不能全为0): 0 0000 0000 01 => 2^0 = 1
则E的范围(1-1023)<= E (2046 - 1023)
复制代码
1.xxx * 2^e
(这是一个规格化的表示),十进制浮点数转二进制, eg:
bash
0.125
x 2 ----
----------------- |
0.25 0 |
x 2 |
----------------- |
0.5 0 |
x 2 |
----------------- |
1.0 1 ↓
复制代码
13.125, 整数部分13 => 1101, 小数部分 0.125 => 0.001函数
13.125 => 1101.001 => 1.101001 * 2^3(存储时,小数点前的1省略了,节省空间)
// 以上S=0; E=3(二进制表示为:10000000010); M=101001,
则二进制表示为:
0 10000000010 1010010000000000000000...
- ----------- -------------------------
s E(1023+3) M,52位长度
复制代码
0.1 转化位二进制: 0.0001100110011(0011循环) => 1.100110011(0011)*2^-4
0.2 转化位二进制: 0.001100110011(0011循环) => 1.100110011(0011)*2^-3spa
a. 多余位 <= 011...11, 舍去。
b. 多余位 = 100...00, 判断尾数的最低有效位的值,若为0则直接舍去,若为1则再加1。
c. 多余位 >= 100...01, 进1。code
0.1 => 0.1100110011001100110011001100110011001100110011001100[1100110011...] => 进1 => 0.1100110011001100110011001100110011001100110011001101
0.2 => 1.1001100110011001100110011001100110011001100110011001[100110011...] => 进1 => 0.1100110011001100110011001100110011001100110011001110
0.1100110011001100110011001100110011001100110011001101 * 2^-3
+ 1.1100110011001100110011001100110011001100110011001110 * 2^-3
----------------------------------------------------------
10.0110011001100110011001100110011001100110011001100111 * 2^-3
=> 1.00110011001100110011001100110011001100110011001100111 * 2^-2
=> 1.0011001100110011001100110011001100110011001100110100 * 2^-2(因为尾数只能52位,就近舍入)
转化为10进制
0.3000000000000000444089209850062616169452667236328125
=> 0.30000000000000004
复制代码
- (2^53, 2^54) 之间的数会两个选一个,只能精确表示偶数
- (2^54, 2^55) 之间的数会四个选一个,只能精确表示4个倍数
- ... 依次跳过更多2的倍数
Math.pow(2, 53) + 3 === Math.pow(2, 53) + 5 // true
Math.pow(2, 54) === Math.pow(2, 54) + 1 // true
Math.pow(2, 54) === Math.pow(2, 54) + 2 // true
复制代码
Math.pow(2, 1024) // Infinity
Math.pow(2, 1023) * 1.999999999999999 // 1.797693134862315e+308
复制代码