JS中的位运算和位移运算

59 阅读4分钟

位运算的概念

将一个整数的二进制格式进行运算

js中,如果对一个数据进行位运算,首先会将其转为一个整数(向下取整),然后按照32位整数的二进制排列。

举例

3.5 => 3 => 0000 0000 0000 0000 0000 0000 0000 0011 
NaN => 0
Infinity => 0
- Infinity => 0

负数的存储方式

-1
真码:1000 0000 0000 0000 0000 0000 0000 0001
反码:1111 1111 1111 1111 1111 1111 1111 1110 真码取反
补码:1111 1111 1111 1111 1111 1111 1111 1111 反码+1 最终的存储方式

与运算(&)

将两个数每一位进行比较,如果都为1,结果为1

例子

1 & 2 => 0
//   0000 0000 0000 0000 0000 0000 0000 0001 
//   0000 0000 0000 0000 0000 0000 0000 0010
//=> 0000 0000 0000 0000 0000 0000 0000 0000

1 & 3 => 1
//   0000 0000 0000 0000 0000 0000 0000 0001 
//   0000 0000 0000 0000 0000 0000 0000 0011
//=> 0000 0000 0000 0000 0000 0000 0000 0001

或运算(|)

将两个数每一位进行比较,只要有一位为1,结果为1

例子

1 | 2 => 3
//   0000 0000 0000 0000 0000 0000 0000 0001 
//   0000 0000 0000 0000 0000 0000 0000 0010
//=> 0000 0000 0000 0000 0000 0000 0000 0011

1 | 3 => 3
//   0000 0000 0000 0000 0000 0000 0000 0001 
//   0000 0000 0000 0000 0000 0000 0000 0011
//=> 0000 0000 0000 0000 0000 0000 0000 0011

非运算(~)

把每一位取反

~1
//   0000 0000 0000 0000 0000 0000 0000 0001 
//   1111 1111 1111 1111 1111 1111 1111 1110

可以看出是一个负数,但负数我们知道是补码的形式,需要:
1. 减一  =>  1111 1111 1111 1111 1111 1111 1111 1101
2. 取反  =>  1000 0000 0000 0000 0000 0000 0000 0010 => -2

所以 ~1 => -2

看起来有点繁琐,可以快速算出来: ~n => (-n - 1)

比如上面的 ~1 = (-1) - 1 = -2  
比如:~-1 = (1) - 1 = 0  
比如:~0 = (-0) - 1 = -1

有个向下取整的快速方法:~~

比如: ~~(3.14) = 3

异或(^)

两个数字按位比较,相同取0,不同取1

1 ^ 2 = 3
//   0000 0000 0000 0000 0000 0000 0000 0001 
//   0000 0000 0000 0000 0000 0000 0000 0010
//=> 0000 0000 0000 0000 0000 0000 0000 0011 3

位移运算

左移(<<)

将数字的二进制(除符号位外),左移动

3 << 1

3: 0000 0000 0000 0000 0000 0000 0000 0011   
>  0000 0000 0000 0000 0000 0000 0000 0110 => 6

规律是:=> 数字 * (2**左移的数字)

2 << 3  => 2 * 8 =>    16
3 << 2  => 2 * 4 =>    12

右移(>>)

将数字的二进制(除符号位外),右移动

3 >> 1

3: 0000 0000 0000 0000 0000 0000 0000 0011   
>  0000 0000 0000 0000 0000 0000 0000 0001 => 1

规律是:=> 数字 / (2**左移的数字)

20 << 3  => 20 / 8  =>    2
10 << 2  => 10 / 4  =>    2