/**
@date 2021-11-21
@description JavaScript位运算
*/
序
JS中的位运算是对于二进制的运算,使用时会转为整数再转为32位二进制进行计算,然后转回来,有以下7个位运算符:
按位与:&
按位或:|
按位非:~
按位异或:^
左移:<<
右移:>>
无符号右移:>>>
按位与(&)
从一句代码来理解&
const bitAnd = 5 & 7; // 5
讲解按位与之前我们需要知道与运算
是什么,其实就是我们常说的与或非
中的与
,那么就很简单了,先梳理以下与
的运算结果
value | value | result |
---|---|---|
1 | 1 | 1 |
1 | 0 | 0 |
0 | 1 | 0 |
0 | 0 | 0 |
然后再看按位与
,就是按每一位做与运算
,那么分析题目5 & 7
5 => 00000000000000000000000000000101
7 => 00000000000000000000000000000111
& => 00000000000000000000000000000101 => 5
最后得到的是二进制的101
,转回十进制就是5
,由此可见按位与
是很简单的,只要利用与运算
就能得到答案
按位或(|)
同上按位与,按位或也需要理解或运算
:
value | value | result |
---|---|---|
1 | 1 | 1 |
1 | 0 | 1 |
0 | 1 | 1 |
0 | 0 | 0 |
再做5 | 7
:
5 => 00000000000000000000000000000101
7 => 00000000000000000000000000000111
| => 00000000000000000000000000000111 => 7
得到111
,转回十进制就是7
按位非(~)
同理,先看非运算
:
value | result |
---|---|
1 | 0 |
0 | 1 |
但是,再计算~5
后,你会发现与预期不一样:
5 => 00000000000000000000000000000101
~ => 11111111111111111111111111111010
能看到得到了一个负数,因为首位是1
,不过由于JS采用补码
表示负数,那么我们又需要做一些处理才能得到最后的结果,那么问题来了,什么是补码
?
简单的总结一下原码
,反码
,补码
:
原码:首位表示符号位,其余部分为值,如5
的原码是0000000000000000000000000000000000000101
,-5的原码是1000000000000000000000000000000000000101
;
反码:正数的反码就是本身,负数的反码在符号位不变的情况下,其余部分取反,如5
的反码就是0000000000000000000000000000000000000101
,-5的反码是11111111111111111111111111111010
;
补码:正数的补码就是本身,负数的补码是在反码的基础上+1
,如5
的补码是0000000000000000000000000000000000000101
,-5的补码是11111111111111111111111111111011
;
那么也就是说,我们还需要将上面的11111111111111111111111111111010
转回原码,再做下一步的处理,补码转原码,就是补码-1
再取反码:
11111111111111111111111111111010 => 11111111111111111111111111111001 => 10000000000000000000000000000110 => -6
如果是对负数做按位非
,则需要先得到补码
,再使用非运算
,然后转换就行:
-5 => 10000000000000000000000000000101 => 11111111111111111111111111111010 => 11111111111111111111111111111011
~ => 00000000000000000000000000000100 => 4
其实可以记住对于任何数字x
,~x = -(x + 1)
按位异或(^)
同上先看异或运算
:
value | value | result |
---|---|---|
1 | 1 | 0 |
1 | 0 | 1 |
0 | 1 | 1 |
0 | 0 | 0 |
再做5 | 7
:
5 => 00000000000000000000000000000101
7 => 00000000000000000000000000000111
^ => 00000000000000000000000000000010 => 2
左移(<<)
根据字面意思就能理解,左移
就是向左移动x
位数
如5 << 7
:
5 => 00000000000000000000000000000101
<< => 00000000000000000000001010000000 => 640
右移(>>)
同理,右移
就是向右移动,移出去就是0
5 >> 7
:
5 => 00000000000000000000000000000101
>> => 00000000000000000000000000000000 => 0
5 >> 2
:
5 => 00000000000000000000000000000101
>> => 00000000000000000000000000000001 => 1
无符号右移(>>>)
与右移差不多,区别在于首位移动后补0
,所以正数与右移是一样的,主要是负数不一样:
-5 >>> 2
:
-5 => 11111111111111111111111111111011(补码)
>>> 2 => 00111111111111111111111111111110 => 1073741822
无符号右移能保证一定得到正数
跋
日常工作中并不建议使用位运算,这样的代码不太好理解,可能会给别人造成困扰,增加工作难度。
但是基本的了解还是需要的,好好学习,从我做起!