位运算符在日常开发中到底怎么用?

像算术运算符、比较运算符、逻辑运算符这些,在实际开发中都会经常用到,唯独位运算符,从未用到。

所以想请教下大家,一般什么场景下会考虑使用位运算符?

阅读 14k
19 个回答

同楼上,如果位运算相对于其他方案没有明显优势,应尽量避免使用。因为位运算对人类而言不够友好,需要加注释告诉别人这是在干嘛:

// 根据协议,该位表示设备就绪与否
const result = a & 4;

一些运算能力低下或网络环境不稳定的小型设备为了提高处理速度和传输速度,会使用特定的传输协议,这些协议会规定一些位的意义,与这些设备通信的时候,用位运算较为合适。

数据加密、算法摘要、压缩传输等,需要考虑性能或者内容大小的场景。
我自己实际使用过的例子举一个

  1. 在进行巨量的流量数据动态展示的时候,使用数值压缩根据具体数据大小整理成Uint8Array,进行紧凑型数据传输,可以将原本JSON传输40M左右(带gzip)的数据,压缩到差不多10M。

业务开发很少用到,能想到的主要是一些权限控制的场景,每一位表示一个权限
底层算法用到的会多一些

写类库时会用到。比如开发微信公众平台的时候,有多种类型的消息

Integer text = 2;
Integer image = 4;
Integer voice = 8;
Integer video = 16;

你写了个消息处理方法支持同时处理text和image时,你可以写

Integer support = text | image;
if(messageType | support == support){
    //自定义消息处理方法
}

将图片/文本消息转发到你的这个处理方法中。

尽量避免使用。

底层很多数值处理,数据转换大部分都是位运算符,因为它可以有效的提高运行效率。
但是唯一的缺陷就是可读性较差,所以不推荐使用。

大部分curd场景本来就不需要呀,有一些"炫技"或者说取巧的写法如楼上说的应该避免使用

Boolean ^= true // 取反
Int >> 1 // 除2

用的较多的地方之一是加解密算法的实现
想体验的话找个相对简单的算法去实现一遍
比如 DES

设计一些 复合权限 系统的时候使用,例如 React 源码中的 fiber 当前的状态

tcp/udp 报文 的解析 需要 用到 位运算

普通的应用大多数用不到位运算。
一般是大规模运算、通信类应用时,需要直接处理二进制数据时,需要处理专门协议时,会用来判断状态等。
此外图形图像处理的库开发中会用到。

就我个人而言,不常用,但会用的一般就是~|这两个运算符;
~位取反运算符。用来转化indexOf返回-1,判断是否存在,有点includespolyfill的感觉

!~'sljkfdsl9lskdjfls'.indexOf('9') // false
!~'sljkfdsl9lskdjfls'.indexOf('0') // true

|按位或。用来转为number类型【整数】;大多数人转数字类型更多时候可能用+单元运算符,其实本人也很常用这个,不过一般只在明确能够转为数字时使用,如果该值可能为其他不可转为数字(即可能NaN)的时候就会考虑使用|;因为位运算返回的肯定是数字

'1'|0 // 1
'-1'|0 // -1
'some'|0 // 0
null | 0 // 0
undefined | 0 // 0

比起+更保险安全,不过这里要考虑是否可能存在大数的情况,因为位运算会转换为32位有符号整数,所以其能表达的最大数字是-2147483648~2147483647,这点要注意,但在实际业务中一般不会碰到,所以大多数情况是可以放心使用的。应用场景比如需要向下取整,比起Math.floor显得简洁保险许多

以上这些只针对JS

对性能要求高或者一些较为晦涩的场景,比如雪花算法,或者像Java里的ThreadPoolExecutorHashMap的散列算法等等,很多很多,进阶大厂必问

    static final int tableSizeFor(int cap) {
        int n = cap - 1;
        n |= n >>> 1;
        n |= n >>> 2;
        n |= n >>> 4;
        n |= n >>> 8;
        n |= n >>> 16;
        return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
    }

绝大多数场景下都可以不用位运算,但是在做网络协议开发的话不用位运算不行。

比如说协议定义某位bit为标识符,在一般的编程语言中最小的单位都是byte,所以需要位运算来获取bit值,例如:

// 接收到的byte为0b10100001
var buf = 0b10100001;
// 解析出第三位bit
console.log((buf & 0b00100000) >> 5);

常见的TCP和WebSocket协议里都会有这种操作。

1、操作系统内核用得多,很多内核结构体或者CPU寄存器,每一位都有特殊的含义,用位运算可以方便操作,不过也不一定要用位运算符,C语言的位域+联合的方式也可以实现对每一位的操作,可读性还强;
2、程序的加密与解密,一般都是对称加密算法实现,例如,把你的二进制程序执行一次位运算,然后修改入口点为解密代码(逆向的位运算)的地址,解密后再调到原来的入口地址。防止代码被静态分析。
3、数学上的运算,左右移与或非做数值的各种操作运算。

const data = [0, 1, 2, 3];
if(~data.findIndex(i => i === 4)) {
    
}

就用过这一个,还是不推荐用。

写汇编,反汇编经常用到 😂

新手上路,请多包涵

普通开发基本用不到

以前接触的一个消防项目,要解析消防设备的状态。数据里有的部分,一个字节8bit,就代表8个状态位。这就需要位运算来解析了

推荐问题
宣传栏