位奇偶校验码需要解释它是如何工作的?

时间:2014-01-02 23:49:43

标签: bit-manipulation xor bit-shift parity

以下是报告给定整数的bit parity的代码:

01: bool parity(unsigned int x)
02: {
03:   x ^= x >> 16;
04:   x ^= x >>  8;
05:   x ^= x >>  4;
06:   x &= 0x0F;
07:   return ((0x6996 >> x) & 1) != 0;
08: }

我发现了here.。虽然在链接中似乎有解释,但我不明白。 以The code first "merges" bits 0 − 15 with bits 16 − 31 using a right shift and XOR (line 3).开头的第一个解释是让我很难理解发生了什么。我试图在他们周围玩,但这没有帮助。如果清楚地说明这项工作的方式,对我这样的初学者来说会很有用 感谢

编辑:从以下帖子:

value      : 1101 1110 1010 1101 1011 1110 1110 1111
value >> 16: 0000 0000 0000 0000 1101 1110 1010 1101
----------------------------------------------------
xor        : 1101 1110 1010 1101 0110 0001 0100 0010

现在再次将此位移8位:

value          : 1101 1110 1010 1101 0110 0001 0100 0010
value >>8      : 0000 0000 1101 1110 1010 1101 0110 0001
 ----------------------------------------------------
xor            : 1101 1110 1110 0001 0100 1100 0010 0011

所以这里的平价合并在哪里?

2 个答案:

答案 0 :(得分:2)

让我们先用一个2位示例开始,这样你就可以看到发生了什么。四种可能性是:

ab  a^b
--  ---
00   0
01   1
10   1
11   0

您可以看到a^b (xor)给出0表示偶数个1位,1表示奇数。这也适用于3位值:

abc  a^b^c
---  -----
000    0
001    1
010    1
011    0
100    1
101    0
110    0
111    1

第3到第6行使用相同的技巧将所有32位合并为一个4位值。第3行将b31-16b15-0合并以提供16位值,然后第4行将结果b15-b8b7-b0合并,然后第5行合并结果b7-b4b3-b0。由于b31-b4(每个xor操作的上半部分)未被该操作清除,因此第6行通过清除它们来处理(使用二进制0000...1111清除除低4位以外的所有操作)。

这里的合并是在分块模式下实现的。通过“分块”,我的意思是它在减少块而不是单个位时处理值,这允许它有效地将值减少到4位大小(它可以这样做,因为xor操作既是关联的又是可交换的) 。替代方案是对nybbles执行七次xor操作而不是三次。或者,在复杂性分析术语中,O(log n)代替O(n)。

假设您的值为0xdeadbeef,即二进制1101 1110 1010 1101 1011 1110 1110 1111。因此合并发生了:

value      : 1101 1110 1010 1101 1011 1110 1110 1111
      >> 16: 0000 0000 0000 0000 1101 1110 1010 1101
----------------------------------------------------
xor        : .... .... .... .... 0110 0001 0100 0010

(使用不相关的位,将来不会使用的位,保留为.个字符。)

对于完成操作:

value      : 1101 1110 1010 1101 1011 1110 1110 1111
      >> 16: 0000 0000 0000 0000 1101 1110 1010 1101
----------------------------------------------------
xor        : .... .... .... .... 0110 0001 0100 0010
      >>  8: .... .... .... .... 0000 0000 0110 0011
----------------------------------------------------
xor        : .... .... .... .... .... .... 0010 0001
      >>  4: .... .... .... .... .... .... 0000 0010
----------------------------------------------------
xor        : .... .... .... .... .... .... .... 0011

并且,在下表中查找0011,我们看到它给出了偶校验(原始值中有24个1位)。仅更改原始值中的一个位(任何位,我选择了最右位)将导致相反的情况:

value      : 1101 1110 1010 1101 1011 1110 1110 1110
      >> 16: 0000 0000 0000 0000 1101 1110 1010 1101
----------------------------------------------------
xor        : .... .... .... .... 0110 0001 0100 0011
      >>  8: .... .... .... .... 0000 0000 0110 0011
----------------------------------------------------
xor        : .... .... .... .... .... .... 0010 0000
      >>  4: .... .... .... .... .... .... 0000 0010
----------------------------------------------------
xor        : .... .... .... .... .... .... .... 0010

下表中的0010是奇校验。

唯一的“魔法”是0x6996值被四位值移位以确保低位被正确设置,然后 位用于决定平价。使用0x6996(二进制0110 1001 1001 0110)的原因是因为二进制值的奇偶性质,如带衬里的页面所示:

Val  Bnry  #1bits  parity (1=odd)
---  ----  ------  --------------
                         +------> 0x6996
                         |
  0  0000     0    even (0)
  1  0001     1    odd  (1)
  2  0010     1    odd  (1)
  3  0011     2    even (0)
  4  0100     1    odd  (1)
  5  0101     2    even (0)
  6  0110     2    even (0)
  7  0111     3    odd  (1)
  8  1000     1    odd  (1)
  9  1001     2    even (0)
 10  1010     2    even (0)
 11  1011     3    odd  (1)
 12  1100     2    even (0)
 13  1101     3    odd  (1)
 14  1110     3    odd  (1)
 15  1111     4    even (0)

请注意,进行最后一次常数移位并非必要。您可以同样轻松地继续合并操作,直到您找到一个位,然后使用该位:

bool parity (unsigned int x) {
  x ^= x >> 16;
  x ^= x >>  8;
  x ^= x >>  4;
  x ^= x >>  2;
  x ^= x >>  1;
  return x & 1;
}

但是,一旦得到值0...15,常量乘以该值可能比两次额外的shift-and-xor操作更快。

答案 1 :(得分:2)

从原始页面

  

位奇偶校验表示给定输入是否包含奇数1。

所以你想加1的数量。代码使用xor运算符来添加位对,

0^1 = 1 bits on
1^0 = 1 bits on
0^0 = 0 bits on
1^1 = 0 bits on (well, 2, but we cast off 2's)

所以前三行计算1的数量(抛1对)。

那应该有帮助...

从原始页面注意,为什么是0x6996,

的描述
  

如果我们以奇偶校验(15)开始编码偶数0和奇数1,那么我们   得到0110 1001 0110 1001 = 0x6996,这是找到的神奇数字   第7行。移位将相关位移到位0.然后一切   除了位0被屏蔽掉了。最后,我们得到0为偶数和1   对于奇数,完全符合要求。