JavaScript中的Number类型是基于IEEE 754标准的双精度(64位)浮点数格式。
一、IEEE 754双精度格式
假设我们要表示数字-12.375
。
1. 符号位 (Sign bit):
对于负数,符号位为1;对于正数或0,符号位为0。
因此,对于-12.375
,符号位是:1
2. 将数字转换为二进制形式:
我们首先将整数和小数部分分开。
整数部分:12
的二进制表示是1100
。
小数部分:
- 0.375 * 2 = 0.75 => 0
- 0.75 * 2 = 1.5 => 1
- 0.5 * 2 = 1.0 => 1
所以,0.375的二进制表示是.011
。
将整数和小数部分组合起来,我们得到:1100.011
。
3. 标准化这个二进制数字:
将它写成二进制科学记数法的形式:
1100.011
= 1.100011 x 2^3
在这里,1.100011
是标准化的尾数,3
是指数。
4. 指数 (Exponent):
根据IEEE 754双精度格式,我们需要为实际的指数加上一个偏移量1023。
所以:3 + 1023 = 1026
1026的二进制是:10000000010
。这是11位的指数部分。
5. 尾数 (Significand, Fraction, Mantissa):
在标准化的二进制形式中,尾数部分的隐式前导1可以被省略(我们已经知道它总是1,除非指数是全0)。因此,我们只需保留小数点后的部分:100011
。
由于尾数部分为52位,我们需要用0填充这个值,直到它有52位长度。但在此示例中,为了简单起见,我们只展示了几位。
组合所有这些部分,我们得到了-12.375
在IEEE 754双精度格式中的表示:
1 10000000010 100011...
注意,这只是一个简化的表示法。在实际的IEEE 754双精度表示中,尾数部分还需要更多的0来达到52位长度。
二、Javascript中的number类型
在 JavaScript 中,number
类型基于 IEEE 754 双精度浮点数标准。这意味着每一个 JavaScript number
类型的值都是由以下三个部分组成的:
- 符号位 (1位): 这个位确定数字是正数(0)还是负数(1)。
- 指数 (11位): 这11个位确定了二进制小数点的位置。
- 尾数/有效数 (52位): 这部分表示实际数字的位,但要注意,正规范化数的前导1是隐式的。
为了进一步解释这个概念,让我们通过几个例子看一下:
-
整数
让我们考虑整数
5
。二进制表示为
101
,转化为浮点格式是1.01 × 2^2
。指数是2,但在双精度中,真实存储的指数值 = 指数 + 1023 = 1025,即
10000000001
。尾数是
01
,在双精度中,尾数需要52位,所以我们填充它,变成010000...
(共52位)。最终表示为:
0 10000000001 010000...000
-
小数
考虑
0.15625
,其二进制表示为0.00101
,标准化后为1.01 × 2^-3
。指数是-3,真实存储的指数值 = -3 + 1023 = 1020,即
01111111100
。尾数是
01
,填充后为010000...000
。最终表示为:
0 01111111100 010000...000
-
特殊值
+Infinity
:0 11111111111 000...000
-Infinity
:1 11111111111 000...000
NaN
: 任何指数为全1和非零尾数的组合,例如:0 11111111111 100...000
-
非规范化数
考虑一个非常小的值,比如
2.2250738585072014e-308
,这是正规范化数的下限。更小的值就变成非规范化数,如2^-1075
。对于非规范化数,指数为
00000000000
。尾数直接表示这个值,不需要前导1。非规范化数实际上是指当一个数值小到指数全都为0时,尾数的含义就变了,尾数默认的前导位“1”变成了“0”。举例来说,
1.01 × 2^2
这个数的尾数是“01”,小数点前面的“1”就是前导位,保存到计算机中时前导位是被省略了的,指数保存到计算机中要加上1023,也就是说看到计算机里面保存的尾数为“01”,指数为“1025”,我们就知道这个数实际上是1.01 × 2^2
。但当指数为0时,前导位就变成0了,也就是当我们看到计算机里面保存的尾数为“01”,指数为“0”,我们就知道这个数实际上是0.01 × 2^(-1022)
而不是1.01 × 2^(-1022)
,注意,计算机中指数为“0”表示“-1022”(非规范化数规定),为“1”也表示“-1022”(因为1-1023=-1022)。非规范化数是为了能表示更多更小的数值。 -
零
正0:
0 00000000000 000...000
负0:
1 00000000000 000...000
希望上面的例子有助于更好地理解在JavaScript中如何使用 IEEE 754 双精度浮点数表示 number
值。