/**
@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
无符号右移能保证一定得到正数
跋
日常工作中并不建议使用位运算,这样的代码不太好理解,可能会给别人造成困扰,增加工作难度。
但是基本的了解还是需要的,好好学习,从我做起!