从字节检查偶校验

时间:2019-05-22 18:18:09

标签: c bit parity

我在Stackoverflow上找到了一段代码,并根据需要对其进行了编辑。来源:How to check if value has even parity of bits or odd?

它就像一种魅力,但是我无法理解它为什么起作用。

我尝试将其写出,例如字节0b01101101。

   01101101
   00000110
   -------- ^
   01101011
   00011010
   -------- ^
   01110001
   00111000
   -------- ^
   01001001

虽然我的单元测试给出了答案; 1

uint8_t check_even_parity(uint8_t value){
     value ^= value >> 4;
     value ^= value >> 2;
     value ^= value >> 1;

     return value & 1;
}

预期为; 0 尝试写出时的实际结果; 01001001

2 个答案:

答案 0 :(得分:2)

每个步骤组合两个比特集L和R,以使L的奇偶校验与R的奇偶校验合并。 R最终具有与L + R最初相同的奇偶校验。

在步骤1中,我们取8位,并产生一个与8位奇偶校验相同的4位数字。在第2步中,我们产生与4具有相同奇偶性的2位数字。在最后一步中,我们产生与2与2具有相同奇偶性的1位数字。这意味着在三步中,我们得到具有相同奇偶性的一位与原始8位相同。

让我告诉您一次意味着什么。

  1. 让我们从第一步开始,其中L是左4位(0110),R是右4位(1101)。

    xxxx1101 (R)
    xxxx0110 (L)
    --------
    xxxx1011 (R^L)
    

    我已经前进了,对每个数字的左半部分进行x运算。这些位无关紧要。您将了解为什么,随着我们的前进:越来越少的位与每个步骤相关。

    L是偶数,R是奇数,这意味着L + R是奇数。因此,R ^ = L应该使R具有奇校验。可以?的确如此。 0110有两个设置位,因此R ^ = 0110翻转R的两个位。翻转偶数位不会更改奇偶校验。 R保持奇数

  2. 第二步,L是左2位(10),R是右2位(11)。

    xxxxxx11 (R)
    xxxxxx10 (L)
    --------
    xxxxxx01 (L^R)
    

    现在将六位输出。我们只关心每个数字中的两位。

    这次L是奇数,R是偶数。结合起来,L + R是奇数,因此这一次我们需要翻转R的奇偶校验。 R ^ = L可以吗?再次,确实如此。 L设置了奇数个位,因此对其进行异或运算将翻转R的奇数个位,从而确保R的奇偶校验被切换。 R变成奇数

  3. 在最后一步中,L和R分别为1位。

    xxxxxxx1 (L)
    xxxxxxx0 (R)
    --------
    xxxxxxx1 (L^R)
    

    L是1,R是0。就像前面的步骤一样,我们希望R ^ = L是奇数,并且是。 R为奇数

很棒。我们从8位奇数奇偶校验开始,通过成功地将两个半部分合并在一起,我们得到了具有相同奇数奇偶校验的1位。

答案 1 :(得分:2)

我想提出一个可以提供一些直觉的隐喻:

想象一下,您面前有4张卡片,需要堆积。作为一个有两只手的人,您可以同时在每只手中拿起一张牌,并将它们放在另一只2顶上,然后拿起其中一对,再将其放在另一只上。

这会在2个步骤中堆放4张牌。

现在想象一下,您需要堆32张牌并拥有16手(或更多)。您可以使用相同的技术:创建16堆2张纸牌,而不是8堆4张纸牌,4堆8张纸牌,2堆16张纸牌,最后是32张纸牌。

这会在5个移动步骤中堆积32张卡片。

现在,根据处理器的能力,将“ pile”替换为“ xor”,将“ cards”替换为“ bits”,将“ hands”替换为“ p”。在5次移位和异或运算中,您将数字的32位异或在一起,如果该数字具有奇偶校验,则得到0,否则得到1。