位运算及在源码中的使用

1,669 阅读4分钟

什么是位运算

在了解什么是位运算之前,让我们先来了解什么是位 ?位指计算机存储信息的最小单位,在二进制数系统中,位是通过0或1来表示。在学习一门编程语言的数据类型时,总会告诉我们 int 的存储需要 4个字节,取值范围为-2 147 483 648 ~ 2 147 483 647 。其实取值范围就是通过 位 计算出来的,由于 1 字节 = 8 位 ,所以 int 中的 1 用二进制表示为0000 0000 0000 0000 0000 0000 0000 0001 。所以位运算就是直接对整数在内存中的二进制位进行操作。

接下来先介绍下二进制和十进制的转换方式

十进制转二进制(正数) ---- 除2取余,逆序排列 (ps: 小数和负数转换不一样)

二进制转十进制 ---- 按权相加法

运算符

1、按位与(&) 均1返1

10 & 13
10 : 0000 0000 0000 1010
13 : 0000 0000 0000 1101
------------------------------------------
结果:0000 0000 0000 1000

2、按位或(|) 有1返1

42 | 13
42 : 0000 0000 0010 1010
13 : 0000 0000 0000 1101
------------------------------------------
结果:0000 0000 0010 1111

3、按位异或(^) 不同返1,相同返0

42 ^ 13
42 : 0000 0000 0010 1010
13 : 0000 0000 0000 1101
------------------------------------------
结果:0000 0000 0010 0111

4、按位取反(~) 所有位取反 (二进制的反码)

42 : 0000 0000 0010 1010
------------------------------------------
~42: 1111 1111 1101 0101

5、有符号左移(<<) 往左移动n位

13 << 2
13 : 0000 0000 0000 1101
----------------------------------------
<<2: 0000 0000 0011 0100
13 << 2 的结果为:52 -----> 13 * (2^2) = 52

6、有符号右移(>>) 往右移动n位(拷贝最左侧位填充到最左侧)

13 >> 2
13 : 0000 0000 0000 1101
----------------------------------------
>>2: 0000 0000 0000 0011
13 >> 2 的结果为:3 -----> 13 / (2^2) = 3 

7、无符号右移(>>>) (最左侧位用0填充,所以结果一定是非0的

位运算的应用

1、判断奇偶数

// 偶数 & 1 = 0
// 奇数 & 1 = 1
console.log(2 & 1)    // 0
console.log(3 & 1)    // 1

从前面的二进制转十进制方法可以知道,除了最右边的位是1 X 1* 0 = 1,其他位数都是1乘以2的n次方,所以其他位数一定是偶数,由此可以得出,最后一位为1的时候一定是奇数。

2、两个数值的变量交换

var a = 5
var b = 8
a ^= b
b ^= a
a ^= b
console.log(a)   // 8
console.log(b)   // 5

关键点

b = (a ^ b) ^ b = a ^ (b ^ b) = a ^ 0 = a;

相同的两个数按位异或为0,一个数按位异或0为本身。

3、权限认证 、类型判断

场景:后台管理系统,操作权限分为一级、二级、三级管理员,其中一级管理员拥有最高的权限,二、三级较低,有些操作只允许一、二级管理员操作,有些操作只允许一、三级管理员操作。现在已经登陆的某权限的用户要进行某个操作,要用怎样的数据结构能很方便地判断他能不能进行这个操作呢?我们用位来表示管理权限,一级用第3位,二级用第2位,三级用第1位,即一级的权限表示为0b100 = 4,二级权限表示为0b010 = 2,三级权限表示为0b001 = 1。如果A操作只能由一级和二级操作,那么这个权限值表示为6 = 0b110,它和一级权限与一下:6 & 4 = 0b110 & 0b100 = 4,得到的值不为0,所以认为有权限,同理和二级权限与一下6 & 2 = 2也不为0,而与三级权限与一下6 & 1 = 0,所以三级没有权限。这里标志位的1表示打开,0表示关闭。这样的好处在于,我们可以用一个数字,而不是一个数组来表示某个操作的权限集,同时在进行权限判断的时候也很方便。

位运算在vue里的实践

VUE3使用静态标记,渲染性能得到提升,这里便使用到了位运算

这里的枚举类型使用有符号左移来表示标签含有的动态类型,在做判断是否存在某个动态标记的时候便可以使用 & 做校验

附上源码地址 源码地址

react也用到了 源码地址

总结

位运算在各大框架和库的源码都可以见到,react、vue、lodash等。懂得位运算可以作为阅读源码的前置知识,在开发系统和组件、库的时候 也可以灵活使用