我不完全理解这种计算奇偶校验位的算法。 有人可以详细解释一下吗?
以下代码摘自“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;
}
答案 0 :(得分:17)
首先是一点理论。
一组位的奇偶校验是 即使1位的数量是偶数,如果是偶数也是奇数 1位数是奇数。
我们将奇偶校验信息编码为:
b0 b1 --> P1-0 –------------------------- 0 ^ 0 --> 0 --> parity even 0 ^ 1 --> 1 --> parity odd 1 ^ 0 --> 1 --> parity odd 1 ^ 1 --> 0 --> parity even
S1
,S2
的奇偶校验计算一组比特S的奇偶校验,使得使用S
=
S1 UNION S2
XOR:P(S) = P(S1) ^ P(S2)
。事实上:
S1
和S2
具有相同的奇偶校验,即它们都具有偶数位或奇数位,则它们的联合S
将具有偶数位S1
和S2
具有不同的奇偶校验,则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
表示具有从m
到n
的位置的位组的奇偶校验。由于我们必须使用不相交的子集计算奇偶校验,我们只使用其中两个奇偶校验值中的一个,我会用?
标记其他奇偶校验值以表示它们没有意义。所以我们有:
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-2
,P9-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位,则会得到您在问题中显示的代码。