像算术运算符、比较运算符、逻辑运算符这些,在实际开发中都会经常用到,唯独位运算符,从未用到。
所以想请教下大家,一般什么场景下会考虑使用位运算符?
数据加密、算法摘要、压缩传输等,需要考虑性能或者内容大小的场景。
我自己实际使用过的例子举一个
写类库时会用到。比如开发微信公众平台的时候,有多种类型的消息
Integer text = 2;
Integer image = 4;
Integer voice = 8;
Integer video = 16;
你写了个消息处理方法支持同时处理text和image时,你可以写
Integer support = text | image;
if(messageType | support == support){
//自定义消息处理方法
}
将图片/文本消息转发到你的这个处理方法中。
就我个人而言,不常用,但会用的一般就是~|
这两个运算符;~
位取反运算符。用来转化indexOf
返回-1
,判断是否存在,有点includes
的polyfill
的感觉
!~'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里的ThreadPoolExecutor
,HashMap
的散列算法等等,很多很多,进阶大厂必问
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、数学上的运算,左右移与或非做数值的各种操作运算。
8 回答4.6k 阅读✓ 已解决
3 回答2.6k 阅读✓ 已解决
6 回答3.4k 阅读✓ 已解决
4 回答4.1k 阅读
3 回答4.1k 阅读✓ 已解决
6 回答2.3k 阅读
5 回答6.3k 阅读✓ 已解决
同楼上,如果位运算相对于其他方案没有明显优势,应尽量避免使用。因为位运算对人类而言不够友好,需要加注释告诉别人这是在干嘛:
一些运算能力低下或网络环境不稳定的小型设备为了提高处理速度和传输速度,会使用特定的传输协议,这些协议会规定一些位的意义,与这些设备通信的时候,用位运算较为合适。