位运算的概念
将一个整数的二进制格式进行运算
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