数字的存储

在对精度要求很高的系统中,或对小数的运算结果进行比较时,需要特别谨慎

问题

  1. JS 中的小数运算是精确的吗?

    不一定

  2. JS 中的整数运算是精确的吗?

    不一定

  3. JS 中表示的整数是连续的吗?

    不是,当 JS 的数字很大的时候,不再连续。

  4. JS 中表示的最大数字是多少

    最大连续整数(Number.MAX_SAFE_INTEGER):9007199254740991

  5. 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
// 一个数的负次方即为这个数的正次方的倒数。
1
2
3
4
5
6

说明:

2的几次方怎么确定?

比如从左数的第一位1,在它前面还有3位,那么它的次数就是为3。

十进制转二进制

13 --> 1101

13 / 261
6  / 230
3  / 211
1  / 201
// 商为0,结束。余数从下往上看
1
2
3
4
5

3.25 --> 11.01

整数部分

3  / 211
1  / 201
//余数从下往上看
1
2
3

小数部分

0.25 * 2     0.5    整数部分:0
0.5  * 2     1.0    整数部分:1
//小数为0,结束。整数部分从上往下看
1
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
......循环
整数部分从上往下看
1
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为底的指数,而不是103段:52位,表示有效数字
1
2
3
4

举例

0     1000 0000 011     1111 0000 0000 0000 ....
1

相当于:$ 1.1111 * 2 ^ {1027 - 1023} $

特殊情况:

  1. 指数为 0,尾数为 0,表示数字 0
  2. 符号为 0,指数为 2047,尾数为 0,表示正无穷
Infinity:0  11111111111  0000000000...
1
  1. 符号为 1,指数为 2047,尾数为 0,表示负无穷
-Infinity:1  11111111111  0000000000...
1
  1. 指数为 2047,尾数不为 0,表示 NaN
NaN:1  11111111111   10010011000...
1

一个正常的数字,指数部分最多是 2046

能表示的最大数字

0  1111 1111 110  1111111111...
1

相当于:1.111111111... * 2 ^ {1023}

能表示的最大安全整数

安全整数:从 1 开始,到该数字,均是连续的整数,并且该数字的下一个整数是存在的。

0  xxxx xxxx xxx  111111111...
1

相当于: 2^{53} - 1

下一位: 2^{53} 0 xxxxxxxxxxx 000000000000...