最近在看很多开源项目的源码,其中位运算应用非常广泛,在此做个总结。
计算机的数字,都是二进制的,而位运算,就是对二进制位进行操作。
一、十进制二进制转换
在总结位运算时,我们先做一点基础:
1、十进制转二进制
比如31,我们一直除以2,都有余数:
从下到上,取余数,就是11111,补全8位就是00011111。计算机内部表示数的字节单位是定长的,如8位,16位,32位。位数不够时,高位(前面)补零。
如果是负数的话,最高位补1,-31的二进制原码就是10011111。
但是原码并不是计算机中的表示,负数转成二进制的步骤如下:
(1)取原码
(2)原码取反(反码,除符号位)
(3)取反后+1(补码)
所以-31在计算机中表达为:11100001
2、二进制转十进制
首先将二进制数补齐位数,首位如果是0就代表正整数,首位如果是1就代表负整数。
先从后往前乘2的次方,然后相加,具体如下:
对于负数的二进制转十进制,就按上面的步骤反着来,先减一,再取反,就得到正的二进制值,然后转成十进制,加个负号,就是了。
二、位运算
位运算有如下操作:
1、按位与&
只有两个位都是1的时候结果才是1,否则是0。
31的二进制是00011111,18的二进制是00010010,与计算之后,如下:
2、或|
只要有一个是1,结果就是1。1|0=1,0|1=1,1|1=1,0|0=0。
3、异或^
相同就是0,不同就是1。0|0=0,0|1=1,1|0=1,1|1=0。
4、 取反~
就是0=1,1=0。单目运算符。
5、左位移<<
正数负数都是相同的处理方式:高位溢出的丢弃,低位不足的补0。
效果:每移动1位,值乘以2。但有些情况会溢出得到负数。
6、右位移
正数:高位补0,低位溢出的舍去
负数:高位补1,低位溢出的舍去
7、无符号右移
无符号右移就是不管是正数还是负数高位补0。