异或

  在逻辑学中,逻辑算符异或(exclusive or)是对两个运算元的一种逻辑析取类型,符号为 ^ 或 XOR 或 ⊕(编程语言中常用^)。但与一般的逻辑或不同,异或算符的值为真仅当两个运算元中恰有一个的值为真,而另外一个的值为非真。转化为命题,就是:“两者的值不同。”或“有且仅有一个为真。”

定义:

1 ⊕ 1 = 0

0 ⊕ 0 = 0

1 ⊕ 0 = 1

0 ⊕ 1 = 1

真值表:

Y

B = 0

B = 1

A = 0

0

1

A = 1

1

0

表达式:

Y = A’ & B | A & B’

(注意:以下的否全部使用符号')

根据定义我们很容易获得异或两个特性:

恒等律:X ⊕ 0 = X 归零律:X ⊕ X = 0

然后我们使用真值表可以证明:

(1)交换律

A ⊕ B = A' & B | A & B'

B ⊕ A = B' & A | B & A'

  因为&与和|或两个操作满足交换律,所以:

A ⊕ B = B ⊕ A

 

(2)结合律

  (A ⊕ B) ⊕ C

= (A' & B | A & B') ⊕ C

= (A' & B | A & B')' & C | (A' & B | A & B') & C '

= ((A' & B)' & (A & B')')& C | A' & B & C ' | A & B' & C '

= ((A | B') & (A' | B))& C | A' & B & C ' | A & B' & C '

= (A & B | A' & B') & C | A' & B & C ' | A & B' & C '

= A & B & C | A' & B' & C | A' & B & C ' | A & B' & C '

  你可以使用同样推导方法得出(请允许我偷懒一下,数学公式敲起来不容易+_+):

A ⊕ (B ⊕ C)

= A & B & C | A' & B' & C | A' & B & C ' | A & B' & C ' 

  证明过程中使用了如下几个方法:

  &与 |或的交换律、分配律和结合律:

A & B = B & A

A | B = B | A

(A & B) & C = A & (B & C)

(A | B) | C = A | (B | C)

A & (B | C)= A & B | A & C

A | B & C = (A | B) & (A | C)

  摩尔定理:

(A & B)' = A' | B'

(A | B)' = A' & B'

  结论:

交换律:A ⊕ B = B ⊕ A 

结合律:A ⊕ (B ⊕ C) = (A ⊕ B) ⊕ C

  有了归零率和结合律,我们就可以轻松证明:

自反:A ⊕ B ⊕ B = A ⊕ 0 = A

  可能这些特性会很顺其自然的理解,但是如果你在解决问题的时候,你可能会忘记异或的这些特性,所以适当的应用可以让我们加深对异或的理解;

A ⊕ 1 = A'

A ⊕ 0 = A

A ⊕ A = 0

A ⊕ A' = 1

 

(说明:以下的的异或全部使用符号^)

  可能你已经被乱七八糟的公式和演算搞的有点烦了,不就是很简单的异或运算吗?还解释的那么复杂,不要着急,打好了基础,你就站在了巨人的肩膀。

(1)汇编语言将寄存器置零

XOR EAX,EAX

 

(2)异或翻转二进制

0 ^ 1 = 1

1 ^ 1 = 0

  翻转10100001的第6位可以将该数与00100000进行按位异或运算;10100001 ^ 00100000 = 10000001

 

(3)异或判断二进制数中1的数量是奇数还是偶数

  求10100001中1的数量是奇数还是偶数,第一个想到的方法当然是判断最后一位是否为1,让后右移一位,直至变量为0为止。最后判断是奇数还是偶数。

  如果用异或,那把每一位异或,就是:

1 ^ 0 ^ 1 ^ 0 ^ 0 ^ 0 ^ 0 ^ 1 = 1

  结果为1就是奇数个1,结果为0就是偶数个1。

  这条性质可用于奇偶校验(Parity Check),比如在串口通信过程中,每个字节的数据都计算一个校验位,数据和校验位一起发送出去,这样接收方可以根据校验位粗略地判断接收到的数据是否有误,但如果校验位也错了,那可是一个大问题:)。

 

(4)RAID5

  校验和恢复主要利用的了异或的特性:if a ^ b = c then a ^ c = b。一个很好的应用实例是RAID5,使用3块磁盘(A、B、C)组成RAID5阵列,当用户写数据时,将数据分成两部分,分别写到磁盘A和磁盘B,A ^ B的结果写到磁盘C;当读取A的数据时,通过B ^ C可以对A的数据做校验,当A盘出错时,通过B ^ C也可以恢复A盘的数据。这就是RAID5的基本原理。

  但RAID5的实现比上述的描述复杂多了,有兴趣的可以上网查一下。

 

(5)经典题目:不使用其他空间,交换两个值

a = a ^ b;

b = a ^ b; //a ^ b ^ b = a ^ 0 = a;

a = a ^ b;

原文地址:https://www.cnblogs.com/Bita/p/5511720.html