JS 中的位运算
© 转载需要保留原始链接,未经明确许可,禁止商业使用。支持原创 CC BY-NC-SA 4.0
本文涉及内容均为二进制操作
提示
在 JavaScript 中数字存储均为基于 IEEE 754 标准的双精度 64 位的浮点数,但是在位运算时都会当作 32 位进行运算,所以大于 2^32 - 1 的数字在位运算时会丢失高位。
(有符号)左移 <<
num << n:将 num 转为二进制,左移 n 位(输出的结果是十进制的)
10 << 2; // 40
// 10的二进制是 1010,左移两位是 101000,转为十进制就是 40
-10 << 2; // -40
关于这个负数怎么移位 (以 -10 << 2 为例) :
| 序号 | 操作 | 数值表示 |
|---|---|---|
| 1 | 转为二进制 | 10000000 00000000 00000000 00001010 |
| 2 | 无符号整数 | 00000000 00000000 00000000 00001010 |
| 3 | 取反+1 | 11111111 11111111 11111111 11110110 |
| 4 | 移位(低位补 0) | 11111111 11111111 11111111 11011000 |
| 5 | -1 取反 | 00000000 00000000 00000000 000101000 |
| 6 | 补符号位 | 10000000 00000000 00000000 000101000 |
| 7 | 转为十进制 | -40 |
(有符号)右移 >>
num >> n:将 num 转为二进制,右移 n 位(输出的结果是十进制的)
10 >> 2; // 2
// 10的二进制是 1010,右移两位是 10,即 2
-10 >> 2; // -3
负数的情况同样(以 -10 >> 2 为例) :
| 序号 | 操作 | 数值表示 |
|---|---|---|
| 1 | 转为二进制 | 10000000 00000000 00000000 00001010 |
| 2 | 无符号整数 | 00000000 00000000 00000000 00001010 |
| 3 | 取反+1 | 11111111 11111111 11111111 11110110 |
| 4 | 移位(高位补 1) | 11111111 11111111 11111111 11111101 |
| 5 | -1 取反 | 0000000000 00000000 00000000 000011 |
| 6 | 补符号位 | 1000000000 00000000 00000000 000011 |
| 7 | 转为十进制 | -3 |
(无符号)右移 >>>
num >>> n:将 num 转为二进制,右移 n 位(输出的结果是十进制的)
10 >>> 2; // 2
// 10的二进制是1010,右移两位是10,即2
-10 >>> 2;
1073741821;
负数情况同样(以 -10 >>> 2 为例) :
| 序号 | 操作 | 数值表示 |
|---|---|---|
| 1 | 转为二进制 | 10000000 00000000 00000000 00001010 |
| 2 | 无符号整数 | 00000000 00000000 00000000 00001010 |
| 3 | 取反+1 | 11111111 11111111 11111111 11110110 |
| 4 | 移位(高位补 0) | 00111111 11111111 11111111 11111101 |
| 5 | 转为十进制 | 1073741821 |
00111111 11111111 11111111 11111101 这个数转为十进制是不好算的,可以间接计算: 2 ** 31 - 2 ** 30 - 3 :
10000000 00000000 00000000 00000000
- 01000000 00000000 00000000 00000000
- 00000000 00000000 00000000 00000011
按位与 &
num1 & num2:转为二进制,按位相与: 同 1 则 1, 符号位参与运算
| 1&1=1 | 1&0=0 | 0&1=0 | 0&0=0 |
10 & 2; // 2
/*
10的二进制是 1010
2的二进制是 0010
按位与的结果是 0010,也就是 2
*/
// 连同符号位一起运算
-10 & 2; // 2
10 & -2; // 10
-10 & -2; // -10
按位或 |
num1 & num2:转为二进制,按位相或: 同 0 则 0,符号位参与运算
| 1|1=1 | 1|0=1 | 0|1=1 | 0|0=0 |
10 | 2; // 10
/*
10的二进制是 1010
2的二进制是 0010
结果是1010,也就是10
*/
//连同符号位一起运算
-10 | 2; // -10
10 | -2; // -2
-10 | -2; // -2
按位非 ~
~num:转换为二进制按位取反: 0 变 1,1 变 0,符号位参与运算
~10; // -11
/*
10的二进制是0000 1010
按位取反后是1111 0101
对应的是 -11 的补码:1111 0101 减去 1 得到 1111 0100 取反(符号位不运算)得到 1000 1011
*/
负数补码是由原码
取反+1后得到的,所以通过补码可以反推原码,注意求原码的过程符号位不参与运算。
异或 ^
num1^num2:转为二进制,按位异或: 异则 1,同则 0,符号位参与运算
| 1^1=0 | 1^0=1 | 0^1=1 | 0^0=0 |
10 ^ 2; // 8
/*
10的二进制是 1010
2的二进制是 0010
结果是1000,也就是 8
*/
//连同符号位一起运算
-10 ^ 2; //-12
10 ^ -2; // -12
-10 ^ -2; //8