概述
计算机世界里难免会接触一些二进制的知识(当然完全不接触也是可能的),因为二进制在一些场景下确实可以方便我们不少,例如:网络接口协议中关于开关、类型等的定义,关于互斥常见的判断等等,在一定程度可以简化我们的接口协议和代码,某种程度可以提高一些执行性能。
二进制的常见操作
其实二进制的操作主要是位运算,但是我在日常开发中使用最多也就是按位与(&)操作了。当然其他的操作也有很大的用处,或许只是我没有遇到使用场景吧,后面如果遇到了,也在这里进行补充。
按位与
按位与操作其实就是将二进制数进行按位对其,依次比较,如果相同位上的数字都是1那么这个位得到结果就是1,否则就是0,例如:
213 = 1*2^7 + 1*2^6 + 0*2^5 + 1*2^4 + 0*2^3 + 1*2^2 + 0*2^1 + 1*2^0
1 1 0 1 0 1 0 1
12 = 0*2^7 + 0*2^6 + 0*2^5 + 0*2^4 + 1*2^3 + 1*2^2 + 0*2^1 + 0*2^0
0 0 0 0 1 1 0 0
按位与:0 0 0 0 0 1 0 0
上面就是一个简单的二进制按位与过程,213&12=4,从上面很容易可以发现有一个规律,那就是contain,4是213和12都包含的一个数字拆解,那么在平时开发的时候就可以用来求交集了,是不是很方便?
按位或
按位或的操作指的是两个数字二进制按位对齐,相同位上一个数字是1,那么结果就是1。
213 二进制:11010101
12 二进制:00001100
按位或:11011101
那么也就是说 213|12 的结果是11011101也就是221,这是一个求并集的过程,但是实际开发场景遇到的还是比较少的(我目前没有遇到过这种开发场景)。
按位异或
这个概念有点不太好理解,两个操作数进行二进制按位对齐,相同位上数字不同才会得到结果为1,否则就是0。这么说我觉得好理解一点。
213 二进制:11010101
12 二进制:00001100
按位异或:11011001
按位异或的使用就是两个数字如果按位异或操作结果为0,那么这两个数字肯定是相等的。
使用场景
从上面的说明可以总结几点:
- 判断数字A在二进制运算中是否包含数字B,那么就可以通过A&B==B是否成立来判断
- 判断数字A是否同时存在于数字B和C的数字组合中,可以通过B&C&A==A是否成立
- 判断两个对象是否相同可以通过 AB==0是否成立进行(代表异或)
上面的总结是否有用呢?其实很有用处,而且在很多时候优化性能就靠他们了。
权限
我们很多时候需要对用户进行权限判断,而且大部分情况权限不是独立的,可能存在一个用户有多个权限,这时候我们就可以用到上面的结论:
我们定义用户权限字段为level,权限值分别可取值为1、2、4、8、16、32、64
这个时候当一个用户的level为91,那么他的二进制是1011011,就很容易得到拥有的权限是64、16、8、2、1,当需要判断当前用户是否拥有某种权限也只需要将level和权限值按位与运算一下是否得到权限值自己即可。那么在接口协议中其实就是一个int类型数字而已。
其实Linux系统中的权限就是这么来的
判断奇偶性
我们都知道一个数字被2整除那么就是偶数,否则就是奇数,但是在上面的那么多未操作,有没有发现一个规律,奇数往往意味着最低位是1,也就证明了所有数字与1按位与操作得到1就是奇数
判断对象相同
在Java中每个对象都有一个hashCode方法,在一定程度可以认为hashCode就是对象的唯一标识,那么如果两个对象的hashCode按位异或得到0,就认为对象相等。
总结
二进制在开发中一般很少涉及到,原因是现在代码讲究是阅读得懂,而不讲究简洁。当然原因也是计算机发展很快,现在硬件很强劲了,但是对于底层开发还是需要考虑到一些性能优化的,就例如上面说的权限判断,如果采用普通判断恐怕都要被if-else烦死了,时间久了不一定看得明白,但是二进制就很简单了。
最后邀请大家一起来学习程序中的数学知识,有兴趣可以扫描二维码。