以下是报告给定整数的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
所以这里的平价合并在哪里?
答案 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-16
与b15-0
合并以提供16位值,然后第4行将结果b15-b8
与b7-b0
合并,然后第5行合并结果b7-b4
与b3-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 对于奇数,完全符合要求。