【问题标题】:bit parity code needs explanation as to how it works?位奇偶校验码需要解释它是如何工作的?
【发布时间】:2014-01-20 13:26:09
【问题描述】:

这是报告给定整数的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

那么奇偶校验的合并发生在哪里?

【问题讨论】:

  • 位奇偶校验只是对所有位进行异或运算。上面是在“块”中进行的,以使其更快更简单,除了最后一行肯定有点奇怪。但是,此时,x 中的奇偶校验已减少到 4 位数量,因此最后一行基本上是“查找”x 中 16 个可能值之一的正确奇偶校验值——一个聪明的,如果晦涩难懂,则为捷径。

标签: bit-manipulation xor bit-shift parity


【解决方案1】:

让我们首先从一个 2 位示例开始,以便您了解发生了什么。四种可能性是:

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

您可以看到a^b (xor) 为偶数个位提供 0,为奇数提供 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(每个异或操作的上半部分)没有被该操作清除,第 6 行通过清除它们来解决这个问题(与二进制 0000...1111 一起清除除低 4 位之外的所有位)。

这里的合并是通过分块方式实现的。通过“分块”,我的意思是将值减少为块而不是单个位,这允许它有效地将值减小到 4 位大小(它可以这样做,因为 xor 操作既是关联的又是可交换的) .另一种方法是对 nybbles 执行 7 个异或操作,而不是 3 个。或者,在复杂性分析方面,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,将常数移位该值可能比两个额外的移位和异或操作更快。

【讨论】:

  • Q1:32到16到8到4到2的合并是怎么发生的?你能简单解释一下吗?我理解XORing 偶数位给出零,否则为一
  • 第 6 行发生了什么?
  • @eagertoLearn:我已经添加了对这两点的进一步解释,希望能更清楚。
  • 你提到了zero/irrelevent bits left blank。但是当你右移时,你在右侧填充zeroes,当你xor,x和x>>16时,结果不会是空白吧?
  • @eagertoLearn,我的解释不好,我已经清理过了。当您右移时,零位从 left 侧被推入,而不是右侧。我还将把这个例子扩展到四位。
【解决方案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的描述,

如果我们从 parity(15) 开始以 0 和 1 进行奇数编码,那么我们 得到 0110 1001 0110 1001 = 0x6996,这是在 第 7 行。移位将相关位移动到位 0。然后一切 除了位 0 被屏蔽。最后,我们得到 0 为偶数和 1 为奇数,完全符合要求。

【讨论】:

    猜你喜欢
    • 2015-04-04
    • 1970-01-01
    • 2015-06-29
    • 2014-03-06
    • 1970-01-01
    • 1970-01-01
    • 2021-08-29
    • 1970-01-01
    相关资源
    最近更新 更多