异或运算是位运算的一种,符号为:^
运算规则为:相同为0,不同为1
例如
性质:
N ^ 0 = N
N ^ N = 0
A ^ B = B ^ A
(A ^ B) ^ C = A ^ (B ^ C)
public class XorOperation {
public static void main(String[] args) {
System.out.println(zeroXorNonZeroNum(5)); // 5
}
// 0与非零数异或
private static int zeroXorNonZeroNum(int n) {
return 0 ^ n;
}
}
位与位异或,相同为0,不相同为1,所以b的结果为5
public class XorOperation {
public static void main(String[] args) {
System.out.println(nonZeroXorSelf(5)); // 0
}
// 非零数与自身异或
private static int nonZeroXorSelf(int n) {
return n ^ n;
}
}
两个相同的数,二进制都是一样的,所以在位与位进行异或的时候都相同,每一位的结果都是0
public class XorOperation {
public static void main(String[] args) {
System.out.println(twoNonZeroNumXor(3, 8)); // 11
System.out.println(twoNonZeroNumXor(8, 3)); // 11
}
// 两个非零数异或运算
private static int twoNonZeroNumXor(int a, int b) {
return a ^ b;
}
}
因为异或是位与位进行计算的,所以异或的顺序不重要,结果是一样的
int a = 2;
int b = 5;
int c = 4;
int d = (a ^ b) ^ c;
int e = a ^ b ^ c;
int f = a ^ (b ^ c);
System.out.println(d == e); //true
System.out.println(f == e); //true
通过交换律得知,异或的顺序不会影响结果,所以在某一些数先异或,再异或另个数的时候,也不会影响结果,这就是异或满足结合律
异或运算的本质是不带进位的加法
来看一个例子:
(10进制)5 = (二进制)00000101 (10进制)6 = (二进制)00000110
5 ^ 6 计算过程如下:
相同为0,不同为1
来看一个例子:
(10进制)5 = (三进制)00000012 (10进制)6 = (三进制)00000020
5 ^ 6 计算过程如下:
2 ^ 0 = 2,1 ^ 2 = 0
来看一个例子:
(10进制)5 = (四进制)00000011 (10进制)6 = (四进制)00000012
5 ^ 6 计算过程如下:
1 ^ 2 = 3,1 ^ 1 = 2
代码如下:
public class XorOperation {
public static void main(String[] args) {
int a = 4;
int b = 5;
System.out.println("==== exchange before ====");
System.out.println("a = " + a);
System.out.println("b = " + b);
a = a ^ b;
b = a ^ b;
a = a ^ b;
System.out.println("==== exchange after ====");
System.out.println("a = " + a);
System.out.println("b = " + b);
}
}
运行结果
==== exchange before ====
a = 4
b = 5
==== exchange after ====
a = 5
b = 4
代码如下
public class XorOperation {
private static int getRightOne4Num(int n) {
return n & (~n + 1);
}
public static void main(String[] args) {
System.out.println(getRightOne4Num(5));
}
}
运行结果
1
代码如下
public class XorOperation {
public static int countBinaryOne(int n) {
int count = 0;
while (n != 0) {
int rightOne = n & (~n + 1);
count++;
n ^= rightOne;
}
return count;
}
public static void main(String[] args) {
System.out.println(countBinaryOne(5));
}
}
运行结果
2
代码如下
public class XorOperation {
// 数组中,只有一种数,出现奇数次
public static void printOddTimesNum1(int[] arr) {
int eor = 0;
for (int i = 0; i < arr.length; i++) {
eor ^= arr[i];
}
System.out.println(eor);
}
public static void main(String[] args) {
printOddTimesNum1(new int[]{1, 2, 1, 1, 4, 5, 4, 5, 2});
}
}
运行结果
1
代码如下:
public class XorOperation {
public static void printOddTimesNum2(int[] arr) {
int eor = 0;
for (int i = 0; i < arr.length; i++) {
eor ^= arr[i];
}
int rightOne = eor & (~eor + 1);// 取出最右边的1
int onlyOne = 0;
for (int i = 0; i < arr.length; i++) {
if ((arr[i] & rightOne) != 0) {
onlyOne ^= arr[i];
}
}
System.out.println(onlyOne + " " + (eor ^ onlyOne));
}
public static void main(String[] args) {
printOddTimesNum2(new int[]{1, 2, 1, 1, 4, 5, 4, 5});
}
运行结果:
1 2