使用位运算的目的是位运算速度比较快,因为它更接近机器的运算语言
&(and)与运算:都为1是1其他为0
|(or)或运算:都是0是0其余为1
^(not):取反
~(xor)异或运算:同为0或同为1是0其余为1
<<:左移
>>:右移
左移右移位运算可以进行乘法除法运算,<<i左移是乘2的i次方,>>i右移是除2的i次方,>>>是无符号右移(符号位也右移,被0替换)
举个简单的例子,如图:
代码如下:
public class Testwys {
public static void main(String[] args) {
int a=-5;
int b=a<<2;
int c=4;
int d=c<<3;
int e=-6;
int f=e>>2;
int g=e>>>2;
int j=60;
int h=j>>3;
int i=j>>>3;
System.out.println("-5左移<<2==="+b);
System.out.println("4左移<<3==="+d);
System.out.println("-6右移>>2==="+f);
System.out.println("-6无符号右移>>2==="+g);
System.out.println("60右移>>3==="+h);
System.out.println("60无符号右移>>>3==="+i);
}
}
结果如图:
我们可以看到<<左移不管正负符号位都不会变,>>右移不管正负符号位也不会变,而使用>>>无符号位移符时符号位不管正负都会变成正的
&与运算可以判断奇偶性,i&1==0时为偶数否则为奇数
原理如下图(因为二进制1的前面位数都为0,与运算后都是0,最后结果只有0和1两种可能):
去掉二进制的最后一个一:i=i&(i-1)
代码如下:
public class Testa {
public static void main(String[] args) {
int i=6;
i=i&(i-1);
int a=5;
a=a&(a-1);
System.out.println("6的二进制110去掉最后一个一==100=="+i);
System.out.println("5的二进制101去掉最后一个一==100=="+a);
}
}
结果如下图:
^异或运算:判断相同a^b==0异或是相同为0不同为1,所以二进制如果完全相同异或后是0。
交换数:用异或交换两个数的时候不用引入第三个数
int a=2;
int b=4;
a=a^b;//a^b=c,c^b=a,c^a=b,也就是把a赋值为成c的 数
b=a^b;//b=a
a=a^b;//a=b
代码可简写成如下,
public class Testa {
public static void main(String[] args) {
int a=2;
int b=4;
System.out.println("交换前(a,b)"+"("+a+","+b+")");
a^=b;
b^=a;
a^=b;
System.out.println("交换前(a,b)"+"("+a+","+b+")");
}
}
结果交换成功:
数组中只出现一次的数其他的数都出现过偶数次找出只出现过一次的数:
public class Testa {
public static void main(String[] args) {
int[] a= {1,1,2,3,3,3,3,4,4};
int flag=0;
for(int i=0;i<a.length;i++) {
flag^=a[i];
}
System.out.println(flag);
}
}
上面知道两个相同的数异或等于0,所以最后flag就等于只出现过一次的数结果如下:
将位运算混合起来使用:例
给定两个整数A, B,写一个方法确定需要几次换位才可以将A变为B。
比如 A: 11010 B: 01100 输出:3
我们首先要知道那些位需要替换,我们很容易想到异或这个功能,A^B,相同的位异或为0,不同的位异或为1,所以我们只需要确定异或之后的数有几个1即可。我们需要确定出这几位一,例如A^B = x, 我们让x&(x-1),这个操作清除了x最右边的1,我们通过一个循环确定次数,直到x为0结束。代码如下:
public class Testa {
public static void main(String[] args) {
int A=26;//二进制11010
int B=12;//二进制01100
int a=bitSwapNums(A,B);
System.out.println(a);
}
public static int bitSwapNums(int a, int b) {
int count = 0;
//a^b找出二进制不同位,用i= i & (i - 1)去二进制最后一个1,直到去完1,i=0时停止循环
for(int i = a ^ b; i > 0; i= i & (i - 1)){
count ++;
}
return count;
}
}
结果如图:
位运算的应用很灵活,我们也可以这样实现 :
public class Testa {
public static void main(String[] args) {
int A=26;//二进制11010
int B=12;//二进制01100
int a=bitSwapNums(A,B);
System.out.println(a);
}
public static int bitSwapNums(int a, int b) {
int count = 0;
//a^b找出二进制不同位,右移运算二进制最后一位是1count加一,直到i=0循环结束
for(int i = a ^ b; i > 0; i = i >> 1) {
count += i & 1; //与运算i&1最后一位是1结果就是1,最后一位是0结果就是0
}
return count;
}
}
结果同样为3。