计算奇偶校验
Posted
技术标签:
【中文标题】计算奇偶校验【英文标题】:Computing the Parity 【发布时间】:2013-06-25 09:53:48 【问题描述】:我不完全理解这种位的算法。 谁能详细解释一下?
以下代码摘自《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;
【问题讨论】:
哪一部分你不明白? 移位和异或的顺序(加1的位数?) 【参考方案1】:先说一点理论。
一组位的奇偶校验是 即使 1 位的数量是偶数,如果 1 位的个数是奇数。
我们将奇偶校验信息编码为:
1 --> 集合的奇偶性是奇数 0 --> 集合的奇偶校验是偶数 可以简单地计算一组两位的奇偶校验 使用 XOR:b0 b1 --> P1-0 -------------- 0 ^ 0 --> 0 --> 奇偶校验 0 ^ 1 --> 1 --> 奇偶校验 1 ^ 0 --> 1 --> 奇偶校验 1 ^ 1 --> 0 --> 奇偶校验一组比特 S 的奇偶校验可以从两个不相交的子集
S1
、S2
的奇偶校验中计算出来,这样 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)
我使用符号Pn-m
表示位置从m
到n
的位集的奇偶性。由于我们必须使用不相交的子集计算奇偶校验,因此我们只使用其中两个奇偶校验值中的一个,我将用?
标记其他奇偶校验值,以表示它们没有意义。所以我们有:
y = y ^ (y >> 2)
(考虑更多高阶位)
再次,由于我们只需要不相交子集的奇偶性,我们忽略结果的一些位以避免重叠集合,即P5-2
、P9-6
等,从而获得:
y = y ^ (y >> 4)
(考虑更多高阶位)
再次,忽略重叠集(为了便于阅读,对 ?
s 进行分组):
y = y ^ (y >> 8)
(考虑到所有 32 位):
再次,忽略重叠集:
你:??? ??? P31-16 ??? ??? ??? ??? P15-0y = y ^ (y >> 16)
return y & 1
所以您可以看到返回的值只是参数x
的位的奇偶校验位P31-0
,这正是我们想要的。
【讨论】:
【参考方案2】:如果 x
只有 1 位,显然 ((x ^ (x >> 1)) & 1
会计算奇偶校验(只是将位相互异或)。
这种模式可以扩展到更多位。
如果你有 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 位,则会得到问题中显示的代码。
【讨论】:
以上是关于计算奇偶校验的主要内容,如果未能解决你的问题,请参考以下文章