位运算无论是在Java语言、Python语言、C/C++还是其它语言都是会经常用到的,所以有必要对这些进行一些总结。

补码

在进行总结之前有必要先介绍一下补码的知识,我们知道当我们想将一个十进制的数字装换成二进制的数字,可以使用“碾转相除法”,也就是通过除2取余的方法得到。那么如何将一个负整数转换成二进制呢?其实,负数是使用补码的形式进行表示的,其转换方式简单的就是:先按整数转换,然后取反加一。
比如将一个十进制的-10用二进制表示:

1
2
3
4
5
6
// 正数10的二进制
0000 1010
//取反
1111 0101
//加1
1111 0110

所以,-10的二进制表示就是:1111 0110

按位与(&)

参加运算的两个数,换算为二进制(0、1)后,进行与运算。只有当相应位上的数都是1时,该位才取1,否则该为为0。

1
2
3
4
5
6
10-10进行按位与(&)运算:
0000 1010
1111 0110
-----------------------
0000 0010
所以:10 & -10 = 0000 0010

按位或(|)

参加运算的两个数,换算为二进制(0、1)后,进行或运算。只要相应位上存在1,那么该位就取1,均不为1,即为0。

1
2
3
4
5
6
10-10进行按位或(|)运算:
0000 1010
1111 0110
-----------------------
1111 1110
所以:10 | -10 = 1111 1110

按位异或(^)

参加运算的两个数,换算为二进制(0、1)后,进行异或运算。只有当相应位上的数字不相同时,该为才取1,若相同,即为0。

1
2
3
4
5
6
10-10进行按位异或(^)运算:
0000 1010
1111 0110
-----------------------
1111 1100
所以:10 ^ -10 = 1111 1100

可以看出,任何数与0异或,结果都是其本身。利用异或还可以实现一个很好的交换算法,用于交换两个数,算法如下:

1
2
3
a = a^b
b = b^a
a = a^b

左移(<<)

参加运算的两个数,换算为二进制(0、1)后,进行左移运算,用来将一个数各二进制位全部向左移动若干位。
左移的格式如下:

1
x<<n

表示元素x左移n位,实际上就是在元素x的二进制下最低位(也就是最右边)补加n个0。

1
2
3
4
5
10左移2位(就相当于在右边加20):
0000 1010
--------------------
0010 1000
所以:10<<2 = 0010 1000

右移(>>)

参加运算的两个数,换算为二进制(0、1)后,进行右移运算,用来将一个数各二进制位全部向右移动若干位。
右移的格式如下:

1
x>>n

表示元素x右移n位。

1
2
3
4
5
10右移2位(就相当于在左边加20):
0000 1010
--------------------
0000 0010
所以:10>>2 = 0000 0010

总结

观察上面不难发现,对于位运算而言,左移一位相当于原数乘以2,左移两位相当于原数乘以4,左移n位相当于乘以2的n次方。同理,对于右移运算而言,右移一位相当于原数除以2,以此类推。需要注意的是,除了以后是没有小数位的,都是取整(想想为什么?)。

文章来源:位运算小结(按位与、按位或、按位异或、取反、左移、右移)