计算奇偶校验

时间:2013-06-27 18:43:41

标签: bit-manipulation parity bitwise-xor

我不完全理解这种计算奇偶校验位的算法。 有人可以详细解释一下吗?

以下代码摘自“Hacker's Delight”一书:

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

2 个答案:

答案 0 :(得分:17)

首先是一点理论。

  • 一组位的奇偶校验是 即使1位的数量是偶数,如果是偶数也是奇数 1位数是奇数。

  • 我们将奇偶校验信息编码为:

    • 1 - >该集的奇偶校验是奇数
    • 0 - >该集的平价是均匀的

  • 可以简单地计算一组两位的奇偶校验 使用XOR:
    b0 b1 --> P1-0
    –-------------------------
    0 ^ 0 --> 0 --> parity even
    0 ^ 1 --> 1 --> parity odd
    1 ^ 0 --> 1 --> parity odd
    1 ^ 1 --> 0 --> parity even
    
  • 可以从两个不相交的子集S1S2的奇偶校验计算一组比特S的奇偶校验,使得使用S = S1 UNION S2 XOR:P(S) = P(S1) ^ P(S2)。事实上:
    • 如果S1S2具有相同的奇偶校验,即它们都具有偶数位或奇数位,则它们的联合S将具有偶数位
    • 如果S1S2具有不同的奇偶校验,则S将具有奇数位。

现在我们能够理解这个技巧,假设unsigned int有32位:它通过对两位(两个相邻位)的子集中的位进行分组来“递归地”计算奇偶校验,然后执行对这些子集进行奇偶校验。然后,它通过使用刚刚计算的2位子集的奇偶校验来检查下一个更大的4位组的奇偶校验。然后它继续使用8位和16位子集。

让我们以图形方式看到它(为了清晰起见,在最不重要的位上):

<强> y = x ^ (x >> 1)

   x:  b7    b6    b5    b4    b3    b2    b1    b0
x>>1:  b8    b7    b6    b5    b4    b3    b2    b1
  y=:  P8-7  P7-6  P6-5  P5-4  P4-3  P3-2  P2-1  P1-0

我使用符号Pn-m表示具有从mn的位置的位组的奇偶校验。由于我们必须使用不相交的子集计算奇偶校验,我们只使用其中两个奇偶校验值中的一个,我会用?标记其他奇偶校验值以表示它们没有意义。所以我们有:

   y:  ?  P7-6  ?  P5-4  ?  P3-2  ?  P1-0

y = y ^ (y >> 2) (考虑更高阶位)

   y:  P15-14 ? P13-12 ? P11-10 ? P9-8   ? P7-6 ? P5-4 ? P3-2 ? P1-0
y>>2:  P17-16 ? P15-14 ? P13-12 ? P11-10 ? P9-8 ? P7-6 ? P5-4 ? P3-2
  y=:  P17-14 ? P15-12 ? P13-10 ? P11-8  ? P9-6 ? P7-4 ? P5-2 ? P3-0

同样,由于我们只需要不相交子集的奇偶校验,我们忽略了结果的某些位以避免重叠集,即P5-2P9-6等,从而获得:

   y:  ?? P15-12 ??? P11-8  ??? P7-4 ??? P3-0

y = y ^ (y >> 4) (考虑更高阶位)

   y:  P23-20 ??? P19-16 ??? P15-12 ??? P11-8  ??? P7-4  ??? P3-0
y>>4:  P27-24 ??? P23-20 ??? P19-16 ??? P15-12 ??? P11-8 ??? P7-4
  y=:  P27-20 ??? P23-16 ??? P19-12 ??? P15-8  ??? P11-4 ??? P7-0

同样,忽略重叠集(并将?分组以便于阅读):

   y:  ???? P23-16 ??? ???? P15-8 ??? ???? P7-0

y = y ^ (y >> 8) (考虑所有32位):

   y:  P31-24 ??? ???? P23-16 ??? ???? P15-8  ??? ???? P7-0
y>>8:  0      000 0000 P31-24 ??? ???? P23-16 ??? ???? P15-8
  y=:  P31-24 ??? ???? P31-16 ??? ???? P23-8  ??? ???? P15-0

再次忽略重叠集:

   y:  ???? ???? P31-16 ??? ???? ???? ???? P15-0

<强> y = y ^ (y >> 16)

    y:  ???? ???? P31-16 ??? ???? ???? ???? P15-0
y>>16:  0000 0000 0      000 0000 ???? ???? P31-16
   y=:  ???? ???? P31-16 ??? ???? ???? ???? P31-0

<强> return y & 1

    y:  ???? ???? P31-16 ??? ???? ???? ???? P31-0
    1:  0000 0000 0      000 0000 0000 0000 1
  y&1:  0000 0000 0      000 0000 0000 0000 P31-0

所以你可以看到返回的值只是参数P31-0的位的奇偶校验位x,这就是我们想要的。

答案 1 :(得分:6)

如果x只有1位,那么显然((x ^ (x >> 1)) & 1会计算奇偶校验(只是相互之间的x或x)。

此模式可以扩展到更多位。

如果你有4位,你得到(至少,这是一种方法)

y = x ^ (x >> 1);
y = y ^ (y >> 2);
return y & 1;

这些位执行此操作:

x = a     b     c     d
y = a   a^b   b^c    c^d
y = a  a^b  a^b^c  a^b^c^d

如果将模式一直扩展到32位,则会得到您在问题中显示的代码。