0%

位运算

取出两个数的补码进行运算,在对补码(解决符号问题)进行位运算,然后反推原码就是结果

为什么

因为负数在运算时,需要转换正数的反码,然后由于符号位的问题,我们知道类似于时钟,10点到八点可以(-2)或者(+10),它们总和为12,同余,每十二进一位,同理,对于负数反码的符号位问题,可以加1进位,解决符号问题(-2的理论对应的是14,就是1110,而1110去掉符号位就是-2的补码,所以要反码加1,用补码进行运算解决符号问题)

按位与 (&)

(有正为正,无正为负)参与运算的两个数,换算成二进制后,进行与运算。只有当相应位上的数都是1时,改位才是1,否则位0

按位或(|)

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

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

按位异或(^)

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

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

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

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

取反(~)

参加运算的两个数,换算为二进制(0、1)后,进行取反运算。每个位上都取相反值,1变成0,0变成1。

1
2
3
4
5
对10进行取反(~)运算:
0000 0000 0000 1010
---------------------
1111 1111 1111 0101
所以:~10 = 1111 1111 1111 0101

左移(<<)

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

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

注意,观察可以发现,左移一位的结果就是原值乘2,左移两位的结果就是原值乘4。

右移(>>)

参加运算的两个数,换算为二进制(0、1)后,进行右移运算,用来将一个数各二进制位全部向右移动若干位。(正数右移高位需补0,负数右移高位需补1)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
正数移位
对10右移2位(就相当于在左边加2个0):
0000 0000 0000 1010
--------------------
0000 0000 0000 0010
所以:10 >> 2 = 0000 0000 0000 0010 = 2

负数移位

原码 -2
1000 0010
补码
1111 1110
右移动两位 -> 退位-1 ->原码
1111 1111 1111 1110 1000 0001 (-1)

注意,观察可以发现,右移一位的结果就是原值除2,左移两位的结果就是原值除4,注意哦,除了以后没有小数位的,都是取整。

本文标题:位运算

文章作者:志者

发布时间:2019年08月16日 - 15:47:00

最后更新:2019年08月28日 - 17:33:45

原始链接:http://witman1999.github.io/位运算.html

许可协议: 署名-非商业性使用-相同方式共享 4.0 国际 转载请保留原文链接及作者。

-------------本文结束感谢您的阅读-------------
copy