数字在JS中的表示法

Posted by Mars . Modified at

IEEE 754 双精度数字表示法

数字在JavaScript中按IEEE 754标准中双精度浮点数(64bit)来表示。一个数占用64位,其格式如下:

754

用这种形式表示出来的数字,叫做这个数值的原码

其中的阶码部分:

  1. 阶码有11位,可表示的数范围是0 ~ 2047,这样对应的指数计算结果是2^0 ~ 2^2047,无法表示很小的小数;
  2. 因为既需要表示很小的小数,又需要表示很大的数,所以标准在这里规定,取-1023作为移位值,也就是在阶码原有的基础上需要减去1023才是实际的指数值;
  3. 这样阶码表示的指数计算结果范围:2^-1023 ~ 2^1024
  4. 这样既可以表示非常小的小数,也可以表示较大的数。

尾码部分:

  1. 因为阶码的存在,由阶码控制小数点的位置;
  2. 阶码的覆盖范围很广(2^-1023 ~ 2^1024),因此小数点可以前移1023位,后移1024位,远远超出了尾码的位数;
  3. 因此对于一个小数,如果它的整数位不为1,总可以通过向后移动小数点的方式,将它转化一个整数位为1的数。例如0.0001001,可以表示为1.001 * 2^-4
  4. 这样设计,可以省出一位尾码,多精确表示一些数字。

特殊的规定

  1. 当指数部分为0(全0),且有效位为0(全0),表示数字0
  2. 当指数部分为255(全1),且有效位为0(全0),表示无穷大无穷小(取决于符号位);
  3. 当指数部分为255(全1),且有效位不为0(非全0),表示不是一个数,也就是NaN

负数的补码表示

为了计算方便,实际保存时:

  • 正数表示为原码本身;
  • 负数表示为原码的补码

补码的含义:

原码符号位不变,其余位置按位取反,然后整体+1。

例如,假设我们用8bit表示一个负数,左起第一位表示符号位,则对于-4

  1. 原码表示为: 10000100
  2. 符号位不变,其余按位取反:11111011;
  3. 整体+1,得到补码:11111100

实际上对于正数a和b,计算机计算a-b时,是a的原码与-b原码的补码相加。例如按上述8bit表示法,计算2-4:

  1. 2的原码:00000010;
  2. -4的补码:11111100;
  3. 计算2-4,实际上是2+(-4): 结果是11111110,第一位为1,表示结果负数的补码;
  4. 把它还原成原码:先-1,再除符号位按位取反;
  5. 得到结果:10000010,为正确结果-2

可准确表示的整数范围

因为尾数部分只有52位,因此只要整数数值转为2进制后,占位不大于52位,即可准确表示。

52位空间可以表示的整数范围是: 0 ~ 253-1

因此,IEEE754 双精度浮点数,可以精确表示-(2^53 - 1)2^53 - 1范围的整数。

计算结果精度不够时的处理方式

标准规定,当一个计算结果数的二进制表示,出现尾数位不够时,需要整体向右移动,然后增大阶码。

这个过程中,执行0舍1入的原则:

  • 如果向右移动后移除的部分是1,则移动完成后需要+1
  • 如果移除的是0,则不需要再进行任何操作。

例如:

0 01111111100 0.1100110011001100110011001100110011001100110011001101

+ 0 01111111100 1.1001100110011001100110011001100110011001100110011010

= 0 01111111100 10.0110011001100110011001100110011001100110011001100111

向右移动后,移除的位为1,则需要补1:

0 01111111101 0011001100110011001100110011001100110011001100110011 1(1 多出,需要舍弃)

最终结果为:

0 01111111101 0011001100110011001100110011001100110011001100110100 (补 1)

执行位运算时,数字不视作IEEE754表示

JS在执行位运算操作时,将数字视为32位二进制串进行操作(同样首位代表正负)。而非上述754表示法。

  • >>是带符号右移,表示移动过程中左侧空出来位置用符号位的值来填充(正数补0,负数补1);
  • >>>是无符号右移,表示移动过程中左侧空出来位置,始终用0来填充;
  • >>>>>移动的位数n >= 32时,先对32取余,再进行移动。,因此 a >> 32a 始终相等。
Keywords: JavaScript
previousPost nextPost
已经有 1000000 个小伙伴看完了这篇推文。