1

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

假设我有几个唯一的 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 状态。但它更多的是供我自己使用,以防止将来意外地将这些条件之一移动到操作之下。

4

3 回答 3

6

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

于 2012-06-08T00:20:18.737 回答
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 语句(而不是误报的可能性)。

于 2012-06-08T00:22:46.627 回答
1

是的。Daniel 的回答为直观地理解为什么 XOR 是完全可逆的提供了一个很好的基础。我觉得你想确保情况总是如此。是时候去兔子洞了!

二进制数(ints以及其他所有内容都归结为)与^运算符一起形成了一个称为group的东西。这意味着 对于ints a和。bc

  1. a ^ b永远也是一个int
  2. a ^ b ^ c总是一样的,不管你先计算什么对。这就是丹尼尔所说的“联想”。
  3. 有一个int( 0) 0 ^ a = a ^ 0 = a。这就是身份,因为用 an 异或 0int不会改变它。
  4. 对于a你选择的任何一个,总是,总是,总是 b这样a ^ b = b ^ a = 0。在这种情况下,b被称为相反的a,因为它中和a以给出身份。你也可以证明每个数字只有一个这样的逆,但我不会那样做。

现在,特定的一对ints^还有两个属性使您所说的成为可能。

  1. a ^ b == b ^ a对于任何a& b。这就是丹尼尔所说的“交换”的意思。
  2. a ^ a = 0,这意味着 anint是它自己的逆关于^

使用这个,让我们以你的表达为例。完成所有操作后得到的最终结果是:

C1 ^ C3 ^ C5 ^ C1 ^ C3 ^ C5

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

C1 ^ C1 ^ C3 ^ C3 ^ C5 ^ C5

由于关联性和自逆的东西,我们得到:

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

你可以用同样的逻辑用任何表达方式让自己放心。这将永远是真的。您获得中间值 0 的事实并不重要。实际上,任何值都无关紧要。数学帮你搞定。

于 2012-06-08T11:43:51.407 回答