js中的位运算符(>>、>>>、|、<<、^、~)

  |  

2 进制转换成 10 进制

在这里插入图片描述

10 进制转换成二进制

在这里插入图片描述

右移运算符(>>)

表示将一个数的二进制值向右移动指定的位数,头部补 0,即除以 2 的指定次方(最高位即符号位不参与移动)。 (最后结果数相当于向下取整)

1
2
3
4
5
6
7
8
9
10
11
12
13
4 >> 1
// 2

// 因为4的二进制形式为 00000000000000000000000000000100,
// 右移一位得到 00000000000000000000000000000010,
// 即为十进制的2

-4 >> 1
// -2

// 因为-4的二进制形式为 11111111111111111111111111111100,
// 右移一位,头部补1,得到 11111111111111111111111111111110,
// 即为十进制的-2

右移运算可以模拟 2 的整除运算

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
5 >> 1
// 2
// 相当于 5 / 2 = 2

21 >> 2
// 5
// 相当于 21 / 4 = 5

21 >> 3
// 2
// 相当于 21 / 8 = 2

21 >> 4
// 1
// 相当于 21 / 16 = 1

右移运算可以用来取整

1
2
3
4
5
123.456 >> 0
// 123

-123.456 >> 0
// 123

带符号位的右移运算符(>>>)

表示将一个数的二进制形式向右移动,包括符号位也参与移动,头部补 0。所以,该运算总是得到正值。对于正数,该运算的结果与右移运算符(>>)完全一致,区别主要在于负数。

1
2
3
4
5
6
7
8
9
4 >>> 1
// 2

-4 >>> 1
// 2147483646

// 因为-4的二进制形式为11111111111111111111111111111100,
// 带符号位的右移一位,得到01111111111111111111111111111110,
// 即为十进制的2147483646。

这个运算实际上将一个值转为 32 位无符号整数。

查看一个负整数在计算机内部的储存形式,最快的方法就是使用这个运算符

1
-1 >>> 0 // 4294967295

上面代码表示,-1 作为 32 位整数时,内部的储存形式使用无符号整数格式解读,值为 4294967295(即(2^32)-1,等于 11111111111111111111111111111111)。

左移运算符(<<)

左移运算符(<<)表示将一个数的二进制值向左移动指定的位数,尾部补 0,即乘以 2 的指定次方(最高位即符号位不参与移动)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
4 >> 1
// 2
/*
// 因为4的二进制形式为 00000000000000000000000000000100,
// 右移一位得到 00000000000000000000000000000010,
// 即为十进制的2
*/

-4 >> 1
// -2
/*
// 因为-4的二进制形式为 11111111111111111111111111111100,
// 右移一位,头部补1,得到 11111111111111111111111111111110,
// 即为十进制的-2
*/

二进制或运算符(|)

二进制或运算符(|)逐位比较两个运算子,两个二进制位之中只要有一个为 1,就返回 1,否则返回 0。

1
2
0 | 3 // 3
3| 3 // 3

上面代码中,0 和 3 的二进制形式分别是 00 和 11,所以进行二进制或运算会得到 11(即 3)。

位运算只对整数有效,遇到小数时,会将小数部分舍去,只保留整数部分。所以,将一个小数与 0 进行二进制或运算,等同于对该数去除小数部分,即取整数位。

1
2
2.9 | 0 // 2
-2.9 | 0 // -2

需要注意的是,这种取整方法不适用超过 32 位整数最大值 2147483647 的数。

1
2
2147483649.4 | 0;
// -2147483647

二进制与运算符(&)

二进制与运算符(&)的规则是逐位比较两个运算子,两个二进制位之中只要有一个位为 0,就返回 0,否则返回 1。

1
0 & 3 // 0

上面代码中,0(二进制 00)和 3(二进制 11)进行二进制与运算会得到 00(即 0)。

二进制否运算符(~)

二进制否运算符(~)将每个二进制位都变为相反值(0 变为 1,1 变为 0)。它的返回结果有时比较难理解,因为涉及到计算机内部的数值表示机制。
(所有的位运算都只对整数有效)使用二进制否运算取整,是所有取整方法中最快的一种

1
~ 3 // -4

上面表达式对 3 进行二进制否运算,得到-4。之所以会有这样的结果,是因为位运算时,JavaScirpt 内部将所有的运算子都转为 32 位的二进制整数再进行运算。

3 的 32 位整数形式是 00000000000000000000000000000011,二进制否运算以后得到 11111111111111111111111111111100。由于第一位(符号位)是 1,所以这个数是一个负数。JavaScript 内部采用补码形式表示负数,即需要将这个数减去 1,再取一次反,然后加上负号,才能得到这个负数对应的 10 进制值。这个数减去 1 等于 11111111111111111111111111111011,再取一次反得到 00000000000000000000000000000100,再加上负号就是-4。考虑到这样的过程比较麻烦,可以简单记忆成,一个数与自身的取反值相加,等于-1。
(相当于 -1 -(3) = -4)

异或运算(^)

异或运算(^)在两个二进制位不同时返回 1,相同时返回 0。

1
0 ^ 3 // 3

上面表达式中,0(二进制 00)与 3(二进制 11)进行异或运算,它们每一个二进制位都不同,所以得到 11(即 3)。

“异或运算”有一个特殊运用,连续对两个数 a 和 b 进行三次异或运算,a^=b; b^=a; a^=b;,可以互换它们的值。这意味着,使用“异或运算”可以在不引入临时变量的前提下,互换两个变量的值。

1
2
3
4
5
6
7
var a = 10;
var b = 99;

a ^= b, b ^= a, a ^= b;

a // 99
b // 10

这是互换两个变量的值的最快方法。
异或运算也可以用来取整。

1
12.9 ^ 0 // 12

运算符参考

文章目录
  1. 1. 2 进制转换成 10 进制
  2. 2. 10 进制转换成二进制
  3. 3. 右移运算符(>>)
  4. 4. 带符号位的右移运算符(>>>)
  5. 5. 左移运算符(<<)
  6. 6. 二进制或运算符(|)
  7. 7. 二进制与运算符(&)
  8. 8. 二进制否运算符(~)
  9. 9. 异或运算(^)