我在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
3条答案
按热度按时间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)。
我已经把每个数字的左半部分都用x划掉了。这些都不重要随着我们的进步,您将看到原因:每一步相关的比特将越来越少。
L是偶数,R是奇数,这意味着L+R是奇数。因此,R ^= L应该使R具有奇奇偶性。是吗?是的。0110有两个设置位,因此R ^= 0110翻转了R的两个位。翻转偶数位不会改变奇偶校验。R仍然是奇数。
1.在第二步中,L是左2位(10),R是右2位(11)。
现在有六位被x去掉了。我们只关心每个数的两个位。
此时L是奇数,R是偶数。组合起来,L+R是奇数,所以这次我们需要翻转R的奇偶性。R ^= L可以这样做吗?再说一次,确实如此。L的位数为奇数,因此异或操作将翻转R的奇数位,保证R的奇偶校验被切换。R变成奇数。
1.在最后一步中,L和R各为1位。
L为1,R为0。就像前面的步骤一样,我们希望R ^= L是奇数,它确实是奇数。R是奇数。
太棒了。我们从8位奇数奇偶校验开始,通过成功地将两半合并在一起,我们得到了1位相同的奇数奇偶校验。
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。
iqih9akk3#