JavaScript中所有的数字都按照IEEE-754标准储存为64位。但是位操作符却是转换为32位数字进行操作的。关于这一点的可用性进行了一些思考。
32带符号整数
先来复习一下32带符号整数的数据表示方式。在计算机中,所有的数据都是被储存为0和1的序列,数字也不例外。比如数字4,通过二进制转换,储存为100
。但是整数在实际业务场景中是存在正负的,如何用01序列来表示一个负数呢。我们可以拿出一个位置,用0或者1来标志这个数字是整数还是负数。
在JS的32带符号整数中,数字从左边的第一位用于标识正负数(1表示负数,0表示整数)。在用二进制转换完毕后,用0补齐不足32位的部分。比如数字8的二进制为1000
。我们先用0补齐到31位0000000000000000000000000001000
,然后在左边第一位放上表示正负的位数,8是正数放上0,因此8在32带符号整数中为00000000000000000000000000001000
。
而如果我们要表示一个负数,比如-18
,我们需要先找到该负数的绝对值18
在32带符号整数中的01序列,为00000000000000000000000000010010
,然我们把所有位上面的数字取反,转为11111111111111111111111111101101
。然后我们把它加上1,得到11111111111111111111111111101110
就是18在32带符号整数中的表示。我们可以在控制台中验证一下:
console.log(0b11111111111111111111111111101110 | 0); // -18
0b11111111111111111111111111101110; // 4294967278
在这里0b
起头表示后续的数字是以二进制
方式来储存。|
位操作,表示同等级位上有1个以及以上的1为1,否则为0,因此| 0
表示为取原数值。但是因为位操作符建立在32带符号整数的规则上,这里| 0
实际上的含义是把前面的数值转换为32带符号整数。因此我们看到我们直接运算0b11111111111111111111111111101110
得到的结果是4294967278
而不是-18
。
位操作符是建立在32位带符号整数
操作上进行的,