C语言 从字节检查偶奇偶校验

ssm49v7z  于 2023-10-16  发布在  其他
关注(0)|答案(3)|浏览(122)

我在Stackoverflow上找到了一段代码,并根据我的需要编辑了它。来源:How to check if value has even parity of bits or odd?
它的工作原理就像一个魅力,但我不能让我的头周围为什么它的工作。
我试着把它写出来,例如字节0 b 01101101。

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

z6psavjg

z6psavjg1#

每个步骤组合两个位集L和R,使得L的奇偶校验与R的奇偶校验合并。R最终具有与L+R最初相同的奇偶性。
在步骤1中,我们取8位并产生一个4位数,其奇偶性与8位数相同。在步骤2中,我们生成一个2位数,其奇偶性与4相同。在最后一步中,我们生成一个1位数,其奇偶性与2相同。这意味着在三个步骤中,我们得到一个与原始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仍然是奇数。
1.在第二步中,L是左2位(10),R是右2位(11)。

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

现在有六位被x去掉了。我们只关心每个数的两个位。
此时L是奇数,R是偶数。组合起来,L+R是奇数,所以这次我们需要翻转R的奇偶性。R ^= L可以这样做吗?再说一次,确实如此。L的位数为奇数,因此异或操作将翻转R的奇数位,保证R的奇偶校验被切换。R变成奇数
1.在最后一步中,L和R各为1位。

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

L为1,R为0。就像前面的步骤一样,我们希望R ^= L是奇数,它确实是奇数。R是奇数
太棒了。我们从8位奇数奇偶校验开始,通过成功地将两半合并在一起,我们得到了1位相同的奇数奇偶校验。

mgdq6dx1

mgdq6dx12#

我想提出一个比喻,也许给予一些直觉:
想象一下,你面前有4张牌,你需要把它们堆起来。作为一个有两只手的人,你可以同时拿起每只手的一张牌,把它们放在其他两张牌的上面,然后拿起其中一对牌,把它放在另一张牌的上面。
这在2个移动中堆叠4张牌。
现在想象你需要堆32张牌,有16手(或更多)。你可以使用相同的技术:创建16堆2张牌,然后8堆4张牌,4堆8张牌,2堆16张牌,最后一堆32张牌。
这在5个移动中堆叠32张牌。
现在用“xor”代替“pile”,用“bits”代替“cards”,用处理器的能力代替“hands”。在5个移位和异或中,你得到一个数字的32位异或,如果这个数字有偶数奇偶校验,那么你得到0,否则得到1。

iqih9akk

iqih9akk3#

byte parity_even_bit(byte val)
{
    for(int i=1;i<8;i++)
    {
        val   ^= ((val >> i) & 0x01);
    }
    return (val &= 0x01);
}

相关问题