按位运算符XOR

时间:2017-02-24 21:09:21

标签: c bit-manipulation xor

试图了解XOR的重要性,我找到了这段代码:

  

给定一组数字,其中除了一个数字之外所有元素都出现偶数次,找到奇数出现的数字

但我无法想象它。 XOR按位运算符如何推出奇数元素?

// Function to return the only odd occurring element
int findOdd(int arr[], int n) {
    int res = 0, i;
    for (i = 0; i < n; i++)
        res ^= arr[i];
    return res;
}

int main(void) {
    int arr[] = { 12, 12, 14, 90, 14, 14, 14 };
    int n = sizeof(arr) / sizeof(arr[0]);
    printf("The odd occurring element is %d\n", findOdd(arr, n));
    return 0;
}

输出:The odd occurring element is 90

7 个答案:

答案 0 :(得分:2)

二进制XOR是异或操作,一次执行一位。它相当于减法,模2。

以下是XOR的真值表:

a   b   a^b
1   0    1
1   1    0
0   0    0
0   1    1

如您所见,当输入位的EITHER为1时,XOR将位设置为1(真),但不是两者都是。

现在,考虑一下:什么是1 xor 1?从真相表中,你知道它是零。

什么是1 xor 1 xor 1?好吧,你知道1 ^ 1 == 0,所以留下0 ^ 1,即1。

所以你有x或偶数次1会产生零,奇数次会产生1。

因此,如果我们取a ^ a ^ a,对于a的某个值,我们得到一个结果,其中a的二进制表示中的所有1位都被设置。 (也就是说,我们会回来&#39; a&#39;。)

然而,如果我们取a ^ a ^ a ^ a,对于a的某个值,我们得到一个结果,其中a的二进制表示中的所有1位都是0.(也就是说,我们得到0。)< / p>

当然,对此的一个例外是0. 0的二进制表示没有设置位,因此这种方法不会指示0的数量是偶数还是奇数。

答案 1 :(得分:1)

XOR表示异或,对于操作数中的每个位,如果操作数的相应位为1,则结果位为1,但不是两者:

0 ^ 0 = 01 ^ 0 = 11 ^ 0 = 01 ^ 1 = 0

对于所有值,相同的数字相互取消为x ^ x == 0。 xoring数组的所有元素的最终结果是出现奇数次数,假设只有一个。

如果所有重复的数字只出现偶数次并且只有一个条目出现奇数次,则此方法有效。

答案 2 :(得分:1)

  

但我无法将其可视化

然后你应该一次一行地执行代码,并在循环的每次迭代中密切关注res

或者只是在纸上写下来 - 记下12的二进制形式,即00001100,然后将该值与下一个值进行异或,也是00001100,这会让你回到{{ 1}}。然后用它对Xor表示下一个值,依此类推。您可能希望从一组简短的数字对开始,例如00000000,看看会发生什么。然后尝试删除最后一个,这样你就可以{12, 12, 15, 15}看看你得到了什么。然后尝试重新排序列表:{12, 12, 15}。计算每个位翻转的次数。

答案 3 :(得分:1)

我读它的方式你真的问了两个问题:

  1. XOR的重要性是什么?
  2. XOR如何帮助查找系列中数字奇数?
  3. 为了理解问题(2),必须理解问题(1)。理解问题(1)需要充分介绍XOR逻辑及其所具有的属性。

    XOR的重要性是什么?

    定义:当且仅当TRUE输入的数量为奇数时,XOR运算的输出为TRUE。通常被称为“一个或另一个,但不是两个”

    这由以下真值表捕获: XOR Truth Table

    使用真值表导出以下属性是微不足道的:

    • A ^ 0 = A (输出跟随变量输入)
    • A ^ 1 = A'(输出是变量输入的否定)
    • A ^ A = 0 (由于两个输入相等,输出始终为零)
    • (A ^ B)^ C = A ^(B ^ C)(关联属性)
    • A ^ B = B ^ A (交际财产)

    现在谈谈XOR的重要性,即这些属性如何让人们做出有用的东西。要注意的第一个计算层是硬件层。 XOR门是在许多基本逻辑电路中具有实用性的物理设备,其基本效用是“奇数发生检测”。一些值得注意的应用:

    • 半加器:半加器SUM输出的真值表与XOR门相同。 (将AND门输入进位)。对于全加器,使用XOR门进行基本求和以及一些额外的支持门也是如此。
    • 逆变器:使用一个输入作为控制,另一个作为“输入”,xor门可用于反转输入信号。控制位也可用于传递输入,充当缓冲器。在软件中,您可以使用这些电路将位/字节从一种状态切换到另一种状态。 Val = Val ^ 1(回想上面的第二个属性)。
    • 比较器:当输入不同时,XOR门的输出为1,当它们相同时为0。这是半加器的驱动逻辑。

    除了这些电路,我们还可以在硬件级别使用XOR检查错误检测和纠正(EDAC)操作的字节奇偶校验,交换寄存器值(没有临时变量!),并从中恢复损坏/丢失的数据RAID系统中的硬盘驱动器。

    然而,软件爱好者并不关心这些电路,他们希望生活在抽象的领域,提供一种以人类直观的方式使用这种硬件的简单方法。让代码。

    XOR如何帮助查找系列中数字奇数?

    即使对您的问题的第一条评论表明海报不理解您的问题,但他们无意中正确回答了问题,但我会进一步解释。

    让我们分解你的findOdd()函数实际上在做什么。 for循环实际上执行以下计算:

    结果= 0 ^ 12 ^ 12 ^ 14 ^ 90 ^ 14 ^ 14 ^ 14

    回想一下,XOR是交际的,所以在稍微重新排序后,计算就变成了:

    结果= 0 ^ 12 ^ 12 ^ 14 ^ 14 ^ 14 ^ 14 ^ 90

    使用属性A ^ A = 0和关联性,12和12的XOR与14的XOR一样下降到0,留下:

    结果= 0 ^ 0 ^ 0 ^ 0 ^ 90 = 0 ^ 90 = 90

    实际上,XOR迫使偶数事件变为零,A ^ 0 = A.希望这个详细的XOR描述有助于可视化引擎盖下发生的事情。

答案 4 :(得分:0)

这都是关于XOR运算符的。

git clone有点XOR 例如,
^

根据12^5 == 1100^0101 == (1^0)(1^1)(0^1)(0^1) == 1011的数学定义,如果输入中XOR(s)的数量为奇数,则输出为1

此案例:
当一个数字出现偶数次时,二进制表示在每个位置也会得到两个1或两个1,结果将转到0

例如:

0

请注意,即使出现的数字也没有影响。

答案 5 :(得分:0)

XOR是可交换的:a ^ b等于b ^ a XOR是关联的:a ^ (b ^ c)等于(a ^ b) ^ c

这两个意味着你可以在一系列XOR中任意重新排序操作数。

此外:

0是一个中性元素:a ^ 0等于a 每个数字都是自己的倒数:a ^ a等于0

在我们的代码中,我们正在进行12 ^ 12 ^ 14 ^ 90 ^ 14 ^ 14 ^ 14

我们可以将此重新排序为(12 ^ 12) ^ (14 ^ 14) ^ (14 ^ 14) ^ 90,将与自身偶数次出现的每个元素配对。

这简化为0 ^ 0 ^ 0 ^ 90(因为所有相等元素对相互抵消,给出0),这会减少到90(因为与0进行异或没有)。

答案 6 :(得分:0)

鉴于以下公理:

x ^ x ^ y ^ y ^ y == y
\___/   \_______/
  0   ^     y     == y

然后例如:

x ^ y == y ^ x

此外:

x ^ x ^ x ^ y == x ^ y

所以操作数的顺序无关紧要。

该点是值出现的奇数个值,而偶数结果为0,值为0或0的值为该值。

因此,正如代码开头的注释所暗示的那样,只有当单个值出现奇数且所有其他值出现偶数次时,它才有效。否则,结果只是所有奇数值的xor,例如:

Class A

既不是x也不是y。