位运算不管是在Java语言,还是在C语言中,或者其他语言,都是经常会用到的,所以本文也就不固定以某种语言来举例子了,原始点就从0、1开始。位运算主要包括按位与(&)、按位或(|)、按位异或(^)、取反()、左移(<<)、右移(>>)这几种,其中除了取反()以外,其他的都是二目运算符,即要求运算符左右两侧均有一个运算量。
注意点:由于计算机是存储的补码,所以二进制转换为十进制的时候,
先要将补码转为原码再计算
即除符号位之外,其他位取反,末位再加1
原码转换为补码也是的
我们只用补码表示负数,正数用原码表示。
1 | ||||
---|---|---|---|---|
原码 | 0000 | 0000 | 0000 | 0001 |
取反 | 1111 | 1111 | 1111 | 1110 |
-2 | ||||
原码 | 1000 | 0000 | 0000 | 0010 |
反码 | 1111 | 1111 | 1111 | 1101 |
补码 | 1111 | 1111 | 1111 | 1110 |
2 | ||||
原码 | 0000 | 0000 | 0000 | 0101 |
取反 | 1111 | 1111 | 1111 | 1010 |
-6 | ||||
原码 | 1000 | 0000 | 0000 | 0110 |
反码 | 1111 | 1111 | 1111 | 1001 |
补码 | 1111 | 1111 | 1111 | 1010 |
原码和补码互换的(负数),正数的补码反码和原码是一样的
(唯一的,也是独特的)规则如下:从数的右边往左开始数,遇到“0”不理它,直到遇到第一个“1”为止,以后的每一位数取反即是它的原码或补码,符号位不变,还是“1”(补码的补码是原码)
如原码:11010100 ----- 从右往左数,第一位是0,不理它,第二位还是0不理它,第三位是1,那么从此以后的每位取反,即为它的补码了.答案为:10101100
补码为101011,那么它的原码是什么?一样的.从可往左数,倒数第一位是1,那么以后每位都取反就成它的原码了(因为这个数是一个补码),答案就是:110101
1、补码
在总结按位运算前,有必要先介绍下补码的知识,我们知道当将一个十进制正整数转换为二进制数的时候,只需要通过除2取余的方法即可,但是怎么将一个十进制的负整数转换为二进制数呢?其实,负数是以补码的形式表示,其转换方式,简单的一句话就是:先按正数转换,然后取反加1。
要将十进制的-10用二进制表示,先将10用二进制表示:
0000 0000 0000 1010
取反:
1111 1111 1111 0101
加1:
1111 1111 1111 0110
所以,-10的二进制表示就是:1111 1111 1111 0110
2、按位与(&)
参加运算的两个数,换算为二进制(0、1)后,进行与运算。只有当相应位上的数都是1时,该位才取1,否则该为为0。
将10与-10进行按位与(&)运算:
0000 0000 0000 1010
1111 1111 1111 0110
-----------------------
0000 0000 0000 0010
所以:10 & -10 = 0000 0000 0000 0010
也即 10 & -10 = 0000 0000 0000 0010 = 2
3、按位或(|)
参加运算的两个数,换算为二进制(0、1)后,进行或运算。只要相应位上存在1,那么该位就取1,均不为1,即为0。
将10与-10进行按位或(|)运算:
0000 0000 0000 1010
1111 1111 1111 0110
-----------------------
1111 1111 1111 1110
所以:10 | -10 = 1111 1111 1111 1110
而1111 1111 1111 1110正好为 -2的补码 即10 | -10 = -2
4、按位异或(^)
参加运算的两个数,换算为二进制(0、1)后,进行异或运算。只有当相应位上的数字不相同时,该为才取1,若相同,即为0。
将10与-10进行按位异或(^)运算:
0000 0000 0000 1010
1111 1111 1111 0110
-----------------------
1111 1111 1111 1100
所以:10 ^ -10 = 1111 1111 1111 1100
而1111 1111 1111 1100正好为 -4的补码 即10 ^ -10 = -4
可以看出,任何数与0异或,结果都是其本身。利用异或还可以实现一个很好的交换算法,用于交换两个数,算法如下:
a = a ^ b;
b = b ^ a;
a = a ^ b;
5、取反(~)
参加运算的两个数,换算为二进制(0、1)后,进行取反运算。每个位上都取相反值,1变成0,0变成1。
对10进行取反(~)运算:
0000 0000 0000 1010
---------------------
1111 1111 1111 0101
所以:~10 = 1111 1111 1111 0101
而1111 1111 1111 0101正好为 -11的补码 即~10 = -11
简单记法:对所有整数取反=本身的相反数-1
~9 = -10
~10 = -11
6、左移(<<)
参加运算的两个数,换算为二进制(0、1)后,进行左移运算,用来将一个数各二进制位全部向左移动若干位。
对10左移2位(就相当于在右边加2个0):
0000 0000 0000 1010
--------------------
0000 0000 0010 1000
所以:10 << 2 = 0000 0000 0010 1000 = 40
注意,观察可以发现,左移一位的结果就是原值乘2,左移两位的结果就是原值乘4。
7、右移(>>)
参加运算的两个数,换算为二进制(0、1)后,进行右移运算,用来将一个数各二进制位全部向右移动若干位。
对10右移2位(就相当于在左边加2个0):
0000 0000 0000 1010
--------------------
0000 0000 0000 0010
所以:10 >> 2 = 0000 0000 0000 0010 = 2
注意,观察可以发现,右移一位的结果就是原值除2,左移两位的结果就是原值除4,注意哦,除了以后没有小数位的,都是取整。
PS:左移,正负数都补0,右移,正数则补0,负数则补1表示不影响正负数。