js的位运算符 &、|、^、~、<<、>>、>>>

111 阅读6分钟

JavaScript 使用 32 位按位运算数
JavaScript 将数字存储为 64 位浮点数,但所有按位运算都以 32 位二进制数执行。
在执行位运算之前,JavaScript 将数字转换为 32 位有符号整数。
执行按位操作后,结果将转换回 64 位 JavaScript 数。

一句话总结:第一位符号位,1为负,0为正;后面跟31位的1或0。

1. 按位与&

同位比较,全部是1则为1,否则为0

  • 举例:6 & 3 首先,我们知道位运算符都是按 32位 二进制进行计算,所以我们先将这两个数转成二进制
    6 => 0000 0000 0000 0000 0000 0000 0000 0110
    3 => 0000 0000 0000 0000 0000 0000 0000 0011
    然后按照&的规则,同位比较得到
    0000 0000 0000 0000 0000 0000 0000 0010 => 2
    所以 6 & 3 = 2

2. 按位或|

同位比较,有一个是1则为1,否则为0

  • 举例:6 | 3 6 => 0000 0000 0000 0000 0000 0000 0000 0110
    3 => 0000 0000 0000 0000 0000 0000 0000 0011
    按照|的规则,同位比较得到
    0000 0000 0000 0000 0000 0000 0000 0111 => 7
    所以 6 | 3 = 7

3. 按位异或^

同位比较,有且只有一个是1则为1,否则为0

  • 举例:6 ^ 3 6 => 0000 0000 0000 0000 0000 0000 0000 0110
    3 => 0000 0000 0000 0000 0000 0000 0000 0011
    按照^的规则,同位比较得到
    0000 0000 0000 0000 0000 0000 0000 0101 => 5
    所以 6 ^ 3 = 5

4. 取反~

反转所有位,也就是1变为0,0变为1,包括符号位

  • 举例:6 6 => 0000 0000 0000 0000 0000 0000 0000 0110
    按照
    的规则,取反得到
    1111 1111 1111 1111 1111 1111 1111 1001
    这里我们看到第一个符号位变为了1,说明结果是一个负数,那么这里还需要说明的是,负数在32位二进制中是按照补码的形式存在的: 负数是正数的二进制补码加 1
    所以这里需要反向操作,先减去个1,再进行翻转得到
    1000 0000 0000 0000 0000 0000 0000 0111 => -7
    所以 ~6 = -7

负数的理解:例如7的二进制为0000 0000 0000 0000 0000 0000 0000 0111,那么-7就应该是7的补码加上1,最终得到1111 1111 1111 1111 1111 1111 1111 1001

5. 左位移<<

向左侧平移,右侧补0,超出的部分截取掉

  • 举例:6 << 3 6 => 0000 0000 0000 0000 0000 0000 0000 0110
    向左侧平移3位,右侧补0,左侧溢出的部分截取掉,得到
    0 0000 0000 0000 0000 0000 0000 0110 000 => 48

说明:对于二进制的计算,0 0000 0000 0000 0000 0000 0000 0110 000 => 2的5次方 + 2的4次方Math.pow(2, 5) + Math.pow(2, 4)=32+16=48

5. 有符号右位移>>

向右侧平移,左侧补最左侧的拷贝(也就是符号不变),超出的部分截取掉

  • 举例:6 >> 2 6 => 0000 0000 0000 0000 0000 0000 0000 0110
    00 0000 0000 0000 0000 0000 0000 0000 01 => 1
  • 举例:-6 >> 2 -6 => 1111 1111 1111 1111 1111 1111 1111 1010
    11 1111 1111 1111 1111 1111 1111 1111 10 => -2

6. 无符号右位移>>>

向右侧平移,左侧补0,超出的部分截取掉

  • 举例:6 >>> 2 6 => 0000 0000 0000 0000 0000 0000 0000 0110
    00 0000 0000 0000 0000 0000 0000 0000 01 => 1
  • 举例:-6 >>> 2 -6 => 1111 1111 1111 1111 1111 1111 1111 1010
    00 1111 1111 1111 1111 1111 1111 1111 10 => 1073741822(Math.pow(2, 30) -Math.pow(2, 1))

应用

//1. 取整
//需要注意的是数字要在[-Math.pow(2, 31), Math.pow(2, 31) - 1]之间
console.log(~~11.23) //11

//2. 计算x二进制中1的个数
// Brian Kernighan 算法:x &= (x - 1) 将最后一个1变为0
const countOnes = (x) => {
  let ones = 0;
  while (x > 0) {
      x &= (x - 1);
      ones++;
  }
  return ones;
}
// 6 => 0000 0000 0000 0000 0000 0000 0000 0110
countOnes(6) //2

//3. 替换二进制中的某一位为1
// 6 => 0000 0000 0000 0000 0000 0000 0000 0110
// => 0000 0000 0000 0000 0000 0000 0001 0110 => 22
console.log(6 | (1 << 4)) //22

//4. 判断乘除运算的符号
(a > 0) ^ (b > 0)

刚开始学习二进制的位运算,哪里说的不对希望大佬们指正,还有其他的应用也希望大家不吝赐教,感谢!!

参考 www.w3school.com.cn/js/js_bitwi…