2020-11-20 逻辑运算(异或为什么可以交换值)

2020-11-20  本文已影响0人  宇宙区长李小无

前言

在写冒泡排序的时候,同事看了我的代码,跟我说,你这个数据交换,不需要中转站的,用一个异或操作就可以啦。具体代码是:

a = 2;
b = 3;
// 数据交换(未使用异或)
temp = a;
a = b;
b = temp;
// 数据交换(使用异或)
a = a ^ b;
b = a ^ b;
a = a ^ b;
// a = 3, b = 2;

怎么样,乍一看是不是有点惊奇,别着急,让我们一探究竟。

逻辑门

这八种逻辑门在数字电路中非常重要,但是我们程序员只需要了解即可。

逻辑运算

为什么是异或

二进制数只有两个值,不是0就是1,那么重点来了:
两个数不同就表明他们二进制表示中有一位或者多位不同,如10和12:

10的二进制:1010
12的二进制:1100

一对比,发现这两个数的中间两位数是不同的。那异或运算特点是什么?不同就出1。那说明两个数进行异或以后,他们不同的位置的数就会变成1。

10 ^ 12 // 0110

很明显,中间两位是1,代表10和12的二进制表示,中间两位数是不同的。与上面我们推断出的规律是一样的。

交换位置

两个不同的数想要交换,而我们已经知道了两个数的二进制表示中,哪些位的值是不同的,所以只需要将不同位的数交换即可。

第一次异或
a = 10; // 1010
b = 12;  // 1100
// 第一次
a = a ^ b;  // 0110

此时a的值为0110,b还是原来的值12(1100)。a是代表了原来a和b的差异值(中间两位不同);

第二次异或
b = a(差异值) ^ b(初始b);  // 1010

此时b的值是差异值a和原来b值异或的结果。

注意观察,异或是找不同,可以得出:
已知左边一位数为0,那右边对应位置的数一定是其本身(0代表相同,出0,1代表不同,出1)
已知左边一位数为1,那右边对应位置的数一定取反(0代表不同,出1,1代表相同,出0)

那说明此时b是原来的b值将二进制表示的中间两位进行取反的结果。还记得第一次异或得出了什么结论吗?a与b再二进制表示中 中间两位 不同
既然b已经进行了差异位的取反,那不就变成了原来a的值了吗?--仔细想想

第三次异或
a = a(差异值) ^ b(初始a);  // 1010将中间两位取反,得出1100

第二次异或结束后,差异值0110,中间两位为1,边上两位为0,利用上面的结论,在第三次异或中,得出a的值为b(原来的a)进行差异取反,也就得到了原来的b的值。

结论

异或交换的核心思想就是:

废话

不由感叹数学果然让人头秃,誓要成为数学亡子 [滑稽]。

周五就该下棋,九五至尊不香吗?

上一篇下一篇

猜你喜欢

热点阅读