视频链接:
搞懂位运算(陈潇冰-鹰空)_哔哩哔哩 (゜-゜)つロ 干杯~-bilibiliwww.bilibili.com
位操作
- 性能比普通运算符操作好快,因为位操作是在数值底层完成的
- ECMAScript中所有的数字都以 IEEE 754 64位格式存储
- 位操作不能直接64位表示,流程是,先转成32位,然后进行位操作,再转成64位
- 我们只需要考虑32位即可
位操作就是对二进制进行操作
0表示正、 1表示负
表示法
正数
00000000000000000000000000010011
00010011 或者 10011
负数
- 负数是高位表示
- 专业描述叫"二补数"存储
- 得到一个负数的流程是
- 先取到它绝对值,也就是正数的二进制表示
- 然后补数,就是每个0变成1,每个1变成0
- 结果最后 +1
- 例子:
算出 -11 的二进制:
1. 计算11的二进制
0000 0000 0000 0000 0000 0000 0000 1011
2. 取补数
1111 1111 1111 1111 1111 1111 1111 0100
3. 加1
1111 1111 1111 1111 1111 1111 1111 0100
+ 1
----------------------------------------------------------
1111 1111 1111 1111 1111 1111 1111 0101
位运算
位或 |
- 原则: 只要有1,就得出1,得0的时候,就是两个都是0
- eg:
18 | 7
18 = 0001 0010
7 = 0000 0111
--------------
0001 0111 = 23
位与 &
- 原则: 两个都是1返回1,任何一位是0的时候返回0
- eg
18 & 7
18 = 0001 0010
7 = 0000 0111
--------------
0000 0010 = 2
位非 ~
- 原则: 就是位取反,表现效果,是对当前数值,取反并减一
- eg:
~10
10 = 0000 0000 0000 0000 0000 0000 0000 1010
1111 1111 1111 1111 1111 1111 1111 0101 = -11
- 效果类似:
-num -1
,但是 ~操作要快的多
位异或 ^
- 原则: 只在一位上是1时返回1,(两位都是1或者0,返回0)
- eg:
11^7
11 = 0000 0000 0000 0000 0000 0000 0000 1011
7 = 0000 0000 0000 0000 0000 0000 0000 0111
---------------------------------------------
1100 = 12
左移 <<
- 整体位数左移, eg: 10<<2, 表示10的二进制,左移两位
- 注意: 左移的情况下, 正数左移,补0,负数左移,也补0
- eg:
10<<2
10 = 0000 0000 0000 0000 0000 0000 0000 1010
左移两位,就是首位去掉两个00,填充到后面
00 0000 0000 0000 0000 0000 0000 101000 = 40
10<<3
10 = 0000 0000 0000 0000 0000 0000 0000 1010
左移三位,就是首位去掉两个000,填充到后面
0 0000 0000 0000 0000 0000 0000 1010000 = 80
10<<2 相当于 10 * 2的2次方
10<<3 相当于 10 * 2的3次方
8<<2 相当于 8 * 2的2次方
-10<<2
-10 = 11111111111111111111111111110110
左移2位,左边去掉两位,移动到右面,
11111111111111111111111111011000
右移 >>
- 又称 有符号 右移
- 右移就是整体二进制位数,向右移动, eg: 10>>2 ,10的二进制位数向右移动2位
- 注意: 右移,正数情况下,补0,负数补1
- eg
10>>2
10 = 0000 0000 0000 0000 0000 0000 0000 1010
右移2位,右侧去掉两个,填充到左侧
000000 0000 0000 0000 0000 0000 0000 10 = 2
10>>3
10 = 0000 0000 0000 0000 0000 0000 0000 1010
右移3位,右侧去掉3个,填充到左侧
0000000 0000 0000 0000 0000 0000 0000 1 = 1
36>>3
32 = 0000 0000 0000 0000 0000 0000 0010 0100
右移3位,右侧去掉3个,填充到左侧
0000000 0000 0000 0000 0000 0000 0010 0 = 4
10>>2 相当于 10 除以 2的2次方 , 10/4 最后结果要,能被除进的,也就是商数,就是 2
10>>3 相当于 10 除以 2的3次方 , 10/8, 商数是 1
32>>3 相当于 32 除以 2的3次方 , 32/8, 商数是 4
或者可以这么认为:
num >> n 等价于 Math.floor(number/Math.pow(2,n))
-10>>2
-10 = 11111111111111111111111111110110
右移两位,右面去掉2位,前面补2个1
11111111111111111111111111111101 = -3
-10>>3
-10 = 11111111111111111111111111110110
右移3位,右面去掉3位,前面补3个1
11111111111111111111111111111110 = -2
无符号右移 >>>
- 这个唯一的区别在于,负数情况下,也会补0,意思就是,无符号右移,不论正负,都补0
- 正数的移动和 >>一样,可以选几个例子试试
-36>>>4
-36 = 11111111111111111111111111011100
00001111111111111111111111111101 = 268435453