资源描述
位运算的常用基础知识(资料)
掌握位运算对了解计算机本身具有很大的帮助,下面介绍在位运算方面应该知道的一些常用方法。
(红色语句为口诀,本人自己总结,阅览者看清楚“前”在例子中有标注,两个数操作其实就是前一个数的对应位置的意思)
AND运算: (按位与 : & ) 遇1为前,遇0为0
AND一般都是用来做清“零”操作,
如果我想获得它的前4位:
0101 1111 (前)
AND
1111 0000
=0101 0000
同理,后四位:
0101 1001 (前)
AND
0000 1111
=0000 1001
还有时会用AND运算来判断一个数是奇数还是偶数,很简单只要跟1比较就可以了。
for(int i = 0;i < 100; i++){
if((i & 1) == 0)
System.out.println("偶数:" + i);
}
例子:
5&3=1 遇1为自己 遇0为0 ;
0000 0000 0000 0000 0000 0000 0000 0101
0000 0000 0000 0000 0000 0000 0000 0011
0000 0000 0000 0000 0000 0000 0000 0001
-5&3=3 遇1为自己 遇0为0 ;
1111 1111 1111 1111 1111 1111 1111 1011
0000 0000 0000 0000 0000 0000 0000 0011
0000 0000 0000 0000 0000 0000 0000 0011
OR运算:(按位或: | ) 遇0为前, 遇1为1;
任何数跟“0”运算或者跟自己运算都是自己。
其主要用来将位的值置为“1”,例如将后四位置为1。
1000 1001 (前)
OR
0000 1111
=1000 1111
同理将前四位置为“1”
0001 1001 (前)
OR
1111 0000
=1111 1001
5|3=7 遇0为自己, 遇1为1;
0000 0000 0000 0000 0000 0000 0000 0101
0000 0000 0000 0000 0000 0000 0000 0011
0000 0000 0000 0000 0000 0000 0000 0111
-5|3=-5 遇0为自己, 遇1为1;
1111 1111 1111 1111 1111 1111 1111 1011
0000 0000 0000 0000 0000 0000 0000 0011
1111 1111 1111 1111 1111 1111 1111 1011
XOR运算:(按位异或 : ^) 相同为0 不同为1
5^3=6 相同为0 不同为1
0000 0000 0000 0000 0000 0000 0000 0101
0000 0000 0000 0000 0000 0000 0000 0011
0000 0000 0000 0000 0000 0000 0000 0110
-5^3=-8 相同为0 不同为1
1111 1111 1111 1111 1111 1111 1111 1011
0000 0000 0000 0000 0000 0000 0000 0011
1111 1111 1111 1111 1111 1111 1111 1000
某公司出的面试题,说交换A,B两个值不使用第三者变量。其实XOR用起来很简单:
A = A ^ B
B = B ^ A
A = A ^ B
任何两个相等的值XOR运算后都等于零,上面的等式拆开来就是:
A = A^B
B = B ^ (A ^ B) B被清掉
A = (A ^ B)^ (B ^ A ^ B) 剩下个B
如果等号两边同时具有相同的数,就不用去拆开了:
B = B ^ (A ^ B)
A = A ^ (B ^ A)
A 0101 1001
B 0001 1100
(1)
A 0100 0101 (A = A ^ B)
B 0001 1100
(2)
A 0100 0101
B 0101 1001 (B = B ^ A)
(3)
A 0001 1100 (A = A ^ B)
NOT运算:(按位取反: ~) 0变1,1变0
~5=-6 0变1,1变0
0000 0000 0000 0000 0000 0000 0000 0101
1111 1111 1111 1111 1111 1111 1111 1010
~-5=4 0变1,1变0
1111 1111 1111 1111 1111 1111 1111 1011
0000 0000 0000 0000 0000 0000 0000 0100
移位运算符
包括:
“>> 右移”;“<< 左移”;“>>> 无符号右移”
<<运算:
就是乘2的N次方运算:
3 << 2 = 3 * 2^2 = 12
-3 << 2 = -3 * 2^2 = -12
>>运算:
除2的N次方运算:
16 >> 2 = 16 / 2^2 = 4
-16 >> 2 = -16 / 2^2 = -4
如果不同长度的两个数据进行运算,系统自动将两者的长度对其,高端为补"零",有符号的数符号位始终为"1"。
例子:
-5>>3=-1
1111 1111 1111 1111 1111 1111 1111 1011
1111 1111 1111 1111 1111 1111 1111 1111
其结果与 Math.floor((double)-5/(2*2*2)) 完全相同。
-5<<3=-40
1111 1111 1111 1111 1111 1111 1111 1011
1111 1111 1111 1111 1111 1111 1101 1000
其结果与 -5*2*2*2 完全相同。
5>>3=0
0000 0000 0000 0000 0000 0000 0000 0101
0000 0000 0000 0000 0000 0000 0000 0000
其结果与 5/(2*2*2) 完全相同。
5<<3=40
0000 0000 0000 0000 0000 0000 0000 0101
0000 0000 0000 0000 0000 0000 0010 1000
其结果与 5*2*2*2 完全相同。
-5>>>3=536870911
1111 1111 1111 1111 1111 1111 1111 1011
0001 1111 1111 1111 1111 1111 1111 1111
无论正数、负数,它们的右移、左移、无符号右移 32 位都是其本身,比如 -5<<32=-5、-5>>32=-5、-5>>>32=-5。
一个有趣的现象是,把 1 左移 31 位再右移 31 位,其结果为 -1。
0000 0000 0000 0000 0000 0000 0000 0001
1000 0000 0000 0000 0000 0000 0000 0000
1111 1111 1111 1111 1111 1111 1111 1111
对于10进制的数字,左移一位就是在末尾加上一个0,数值变大10倍。
同理,对于二进制数字,左移一位是在末尾加上一个0,数值变大2被。
所以 x << 3,x就变大 2^3 倍,就是 8*x
右移同理
byte a = 7; // 0000 0111
byte b = ~a;//1111 1000(补)-1
b: (反) 1111 0111
b: (原) 1000 1000 -8
byte d = 19;// 0001 0011
byte e = ~d; //1110 1100(补)-1
e: (反) 1110 1011
e: (原) 1001 0100 -20
byte f = -19; //1001 0011>1110 1100
>1110 1101
~>0001 0010 > 18
展开阅读全文