文章摘要:
1、按位异或,可以简单理解成:不进位加法。即:1+1=0;0+0=0;1+0 =1;
2、任何数和自己异或结果为零。
3、按位异或自反性。两次运算操作,可以将最后的结果还原。
4、任何数和0做异或值不变,和1异或结果为原操作数取反。
5、交换律。不使用中间变量,交换两个数。
一、按位异或具有自反性。即:对同一个数据,进行两次按位异或操作,等于数据本身。
int displayOptions = 0x1100;
int flag = 0x1001;
int result = displayOptions ^ flag;
System.out.println(Integer.toHexString(displayOptions)
+ " ^ " + Integer.toHexString(flag)
+ " = " + Integer.toHexString(result));
//第一次运算:1100 ^ 1001 = 0101
result = result ^ flag;
System.out.println(Integer.toHexString(displayOptions)
+ " ^ " + Integer.toHexString(flag)
+ " = " + Integer.toHexString(result));
// 第二次运算:0101 ^ 1001 = 1100(displayOptions)
//我们还可以直接使用如下的代码直接进行测试:
System.out.println(Integer.toHexString(displayOptions ^ flag ^ flag));
二、应用案例
场景:
大房子中有很多关闭的电灯,随机操作电灯开关,实时显示房间中电灯的状态,并允许一键关闭所有电灯。【只允许使用按位异或】
分析:
1、连续两次操作电灯开关,电灯将处于操作前状态。
2、关闭所有开关。任何数和自己异或结果为零。
实现:
1、定义“大房子”类。
lightFlags 标识房间全部电灯实时状态。
封装电灯操作方法以及一键关闭所有电灯的方法。
/**
* 1、按位运算操作应用。
* 2、走廊灯、厕所灯、厨房灯、主卧灯、次卧灯分别对应一个字段位
* 走廊灯=0000 0001
* 厕所灯=0000 0010
* 厨房灯=0000 0100
* 主卧灯=0000 1000
* 次卧灯=0001 0000
* @author DrodYoung
*/
static class 大房子{
private static final int 走廊灯 = (1 << 0); // 1{0000 0001}
private static final int 厕所灯 = (1 << 1); // 2{0000 0001}
private static final int 厨房灯 = (1 << 2); // 4{0000 0001}
private static final int 主卧灯 = (1 << 3); // 8{0000 0001}
private static final int 次卧灯 = (1 << 4); //16{0000 0001}
private static final int LIGHT_MASK = 走廊灯|
厕所灯|
厨房灯|
主卧灯|
次卧灯;
//lightFlags = 电灯状态标记字段。
private int lightFlags = 0;
private void 操作电灯开关(int flag){
lightFlags ^= flag;
}
//任何数和自己异或结果为零。
private void 让所有的灯关闭(){
操作电灯开关(lightFlags);
}
@Override
public String toString() {
return "房子中电灯状况:\n"
+"走廊灯="+(((lightFlags&走廊灯)!=0)?"开":"关")+"\n"
+"厕所灯="+(((lightFlags&厕所灯)!=0)?"开":"关")+"\n"
+"厨房灯="+(((lightFlags&厨房灯)!=0)?"开":"关")+"\n"
+"主卧灯="+(((lightFlags&主卧灯)!=0)?"开":"关")+"\n"
+"次卧灯="+(((lightFlags&次卧灯)!=0)?"开":"关")+"\n";
}
}
2、测试:
//1、初始化大房子对象
大房子 hourse = new 大房子();
System.out.println(hourse);
//2、操作厨房灯开关
hourse.操作电灯开关(大房子.厨房灯);
System.out.println(hourse);//厨房灯为【开】
//3、再次操作厨房灯开关
hourse.操作电灯开关(大房子.厨房灯);
System.out.println(hourse);//厨房灯为【关】
//4、依次操作主卧灯、次卧灯、走廊灯开关
hourse.操作电灯开关(大房子.主卧灯);
hourse.操作电灯开关(大房子.次卧灯);
hourse.操作电灯开关(大房子.走廊灯);
//5、一键关闭所有灯
hourse.让所有的灯关闭();
System.out.println(hourse);
三、总结:
妙用按位异或,可以让代码更加简洁、高效。本例演示了按位异或的自反性,异或还有其他妙用,我们可以总结如下:
1、按位异或,可以简单理解成:不进位加法。即:1+1=0;0+0=0;1+0 =1;
2、任何数和自己异或结果为零。
3、任何数和0做异或值不变,和1异或结果为原操作数取反。
4、交换律。不使用中间变量,交换两个数。
a=a^b;
b=a^b;
a=a^b;