可以撤消一系列异或吗?

时间:2012-06-08 00:17:29

标签: c bitwise-operators bitwise-xor

我在纸上进行了几次测试,但似乎无法在任何地方找到确认。

假设我有几个独特的8位数字,我将它们混合在一起存储在某个地方。如果我,那么,稍后,将那些相同的数字与存储的数字一起,我将总是得到0?

基本上我有一个条件的枚举,其中一些条件需要在操作发生之前完成。作为一个完整性检查,并确保我不会意外地回来并在以后破坏此代码,我正在考虑将所需的条件一起开始,然后在满足条件时对存储的值进行异常处理。然后就在操作发生之前,确保我们回到0。

类似

sanity_check = C1 ^ C3 ^ C5
...
//Condition one is met
sanity_check ^= C1
...
//Condition 3 is met
sanity_check ^= C3
...
//Condition 5 is met
sanity_check ^= C5
...
if( sanity_check == 0 )
 Do operation

我知道它并非完美无瑕,因为在合适的条件下,我可能会在那里找到一个中间0状态。但它更适合我自己使用,以防止将来意外移动其中一个条件。

3 个答案:

答案 0 :(得分:6)

是的,XOR是可交换和关联的,x ^ x == 0,因此您可以通过再次执行相同的序列来撤消一系列XOR。

答案 1 :(得分:3)

最好使用位字段,其中每个位代表一个条件:

C1 = 1;  // 1 << 0
C2 = 2;  // 1 << 1
C3 = 4;  // 1 << 2
C4 = 8;  // 1 << 3
C5 = 16; // 1 << 4

// Condition one is met
sanity_check |= C1;

....

// If Conditions 1 2 and 4 passed
if((sanity_check & (C1 | C2 | C4)) == (C1 | C2 | C4))

// If Conditions 1 and 2 passed and 3 failed
if((sanity_check & (C1 | C2 | C3)) == (C1 | C2))

这样,当您到达代码中要检查它们的点时,可以使用按位运算符检查不同的条件集。您也可以保证只有满足所有要求时才会输入if语句(而不是误报的可能性)。

答案 2 :(得分:1)

是。 Daniel的回答为直观地理解为什么XOR是完全可逆的提供了一个很好的基础。我觉得你要确定这是 始终 的情况。是时候走下兔子洞了!

二进制数字(ints以及其他所有内容都归结为)和^运算符形成了一个名为group的内容。这意味着对于ints abc

  1. a ^ b始终也是int
  2. a ^ b ^ c始终相同,无论您先计算哪一对。这就是丹尼尔所说的“联想”。
  3. 有一个int00 ^ a = a ^ 0 = a。这是身份,因为带有int的XORing 0不会改变它。
  4. 对于您选择的任何a,始终总是 b,以便a ^ b = b ^ a = 0。在这种情况下,b被称为a的倒数,因为它会中和a以提供身份。您还可以证明每个数字只有一个这样的反转,但我不打算这样做。
  5. 现在,特定的ints^对有两个属性可以实现您所说的可能。

    1. a ^ b == b ^ a适用于任何a&amp; b。这就是丹尼尔所说的“交换”。
    2. a ^ a = 0,这意味着int^相关,它是自己的逆。
    3. 使用这个,我们以你的表达为例。所有操作后得到的最终结果是:

      C1 ^ C3 ^ C5 ^ C1 ^ C3 ^ C5

      现在,因为我们有交换性,我们可以切换它们并将它们配对以获得:

      C1 ^ C1 ^ C3 ^ C3 ^ C5 ^ C5

      由于相关性和自相反的东西,我们得到:

      (C1 ^ C1) ^ (C3 ^ C3) ^ (C5 ^ C5) = 0 ^ 0 ^ 0 = 0

      您可以使用相同的逻辑来确保任何表达方式。这将始终为真。你获得中间0的事实并不重要。事实上,任何价值观都无关紧要。数学让你满意。