数字的存储
在对精度要求很高的系统中,或对小数的运算结果进行比较时,需要特别谨慎
问题
JS 中的小数运算是精确的吗?
不一定
JS 中的整数运算是精确的吗?
不一定
JS 中表示的整数是连续的吗?
不是,当 JS 的数字很大的时候,不再连续。
JS 中表示的最大数字是多少
最大连续整数(Number.MAX_SAFE_INTEGER):9007199254740991
JS 中能表示的数字的有效位数是多少?
16 ~ 17
整数 16 位
小数 17 位
二进制
现实世界中:十进制,10 个数字,逢十进一
计算机世界中:二进制,2 个数字,逢二进一
二进制转十进制
采用按权相加法
1101 --> 1*2^3 + 1*2^2 + 0*2^1 + 1*2^0 = 13
// 8 + 4 + 0 + 1 = 13
11.01 --> 1*2^1 + 1*2^0 + 0*2^{-1} + 1*2^{-2} = 3.25
// 2 + 1 + 0 + 0.25 = 3.25
// 一个数的负次方即为这个数的正次方的倒数。
2
3
4
5
6
说明:
2的几次方怎么确定?
比如从左数的第一位1,在它前面还有3位,那么它的次数就是为3。
十进制转二进制
13 --> 1101
13 / 2 商6 余1
6 / 2 商3 余0
3 / 2 商1 余1
1 / 2 商0 余1
// 商为0,结束。余数从下往上看
2
3
4
5
3.25 --> 11.01
整数部分
3 / 2 商1 余1
1 / 2 商0 余1
//余数从下往上看
2
3
小数部分
0.25 * 2 0.5 整数部分:0
0.5 * 2 1.0 整数部分:1
//小数为0,结束。整数部分从上往下看
2
3
为什么 JS 的小数运算不精确?
十进制的小数,转换为二进制后,可能是无限小数,但是计算机对数字的存储能力有限,一次会丢失一些数据。
十进制数 0.3 --> 0.010011001100110011001100110011001100110011001100110011
0.3*2 0.6 0
0.6*2 1.2 1
0.2*2 0.4 0
0.4*2 0.8 0
0.8*2 1.6 1
0.6*2 1.2 1
0.2*2 0.4 0
......循环
整数部分从上往下看
2
3
4
5
6
7
8
9
JS 如何存储数字?
整数法、浮点法
JS 中,存储的所有数字,都按照浮点法存放。
浮点法存放的数字,叫做浮点数(float),浮点数分为单精度和双精度。
JS 中,使用双精度存放浮点数,IEEE 754。
存放方式
JS 在计算机中,给每个数字开辟一块内存空间,尺寸固定为 64 位。
在计算机中,位(bit)是最小的存储单位,简称位 bit 1 byte = 8 bit 1 KB = 1024 byte 1 MB = 1024 KB 1 GB = 1024 MB
[第1段][第2段][第3段]
第1段:1位,表示符号位,如果为1,是负数,为0,是正数
第2段:11位,表示指数位,这里的指数是2为底的指数,而不是10
第3段:52位,表示有效数字
2
3
4
举例
0 1000 0000 011 1111 0000 0000 0000 ....
相当于:$ 1.1111 * 2 ^ {1027 - 1023} $
特殊情况:
- 指数为 0,尾数为 0,表示数字 0
- 符号为 0,指数为 2047,尾数为 0,表示正无穷
Infinity:0 11111111111 0000000000...
- 符号为 1,指数为 2047,尾数为 0,表示负无穷
-Infinity:1 11111111111 0000000000...
- 指数为 2047,尾数不为 0,表示 NaN
NaN:1 11111111111 10010011000...
一个正常的数字,指数部分最多是 2046
能表示的最大数字
0 1111 1111 110 1111111111...
相当于:1.111111111... * 2 ^ {1023}
能表示的最大安全整数
安全整数:从 1 开始,到该数字,均是连续的整数,并且该数字的下一个整数是存在的。
0 xxxx xxxx xxx 111111111...
相当于: 2^{53} - 1
下一位: 2^{53} 0 xxxxxxxxxxx 000000000000...