从字节检查偶校验
Check even parity from byte
我在 Whosebug 上找到了一段代码并根据需要对其进行了编辑。来源: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
每一步合并两个位集 L 和 R,这样 L 的奇偶校验与 R 的合并。 R 最终具有与 L+R 最初相同的奇偶校验。
在第 1 步中,我们取 8 位并生成一个与 8 位奇偶校验相同的 4 位数字。在第 2 步中,我们生成一个与 4 具有相同奇偶性的 2 位数字。在最后一步中,我们生成一个与 2 具有相同奇偶性的 1 位数字。这意味着在三个步骤中我们得到一个具有相同奇偶性的位奇偶校验为原来的 8.
让我一步一步地告诉你我的意思。
先说第一步,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 保持 奇数.
第二步,L为左2位(10),R为右2位(11)。
xxxxxx11 (R)
xxxxxx10 (L)
--------
xxxxxx01 (L^R)
现在 6 位被 x 掉了。我们只关心每个数字的两位。
这次L是奇数,R是偶数。结合起来,L+R 是奇数,所以这次我们需要翻转 R 的奇偶性。 R ^= L 这样做吗?同样,确实如此。 L 设置了奇数位,因此异或运算将翻转 R 的奇数位,确保 R 的奇偶校验被切换。 R 变为 奇数.
最后一步,L和R各1位。
xxxxxxx1 (L)
xxxxxxx0 (R)
--------
xxxxxxx1 (L^R)
L 为 1,R 为 0。就像前面的步骤一样,我们希望 R ^= L 是奇数,事实也是如此。 R 为 奇数.
太棒了。我们从具有奇校验的 8 位开始,通过成功地将两半合并在一起,我们得到了具有相同奇校验的 1 位。
我想提出一个比喻,可能会给出一些直觉:
想象一下,您面前有 4 张卡片,您需要将它们堆叠起来。作为一个有 2 只手的人,您可以每只手同时拿起一张牌并将它们放在另外 2 只手上,然后拿起其中一对放在另一只手上。
这将在 2 步内堆放 4 张牌。
现在假设您需要堆放 32 张牌并且有 16 手牌(或更多)。您可以使用相同的技巧:创建 16 堆每张 2 张牌、8 堆每张 4 张牌、4 堆每张 8 张牌、2 堆每张 16 张牌,最后是单堆每张 32 张牌。
这在 5 步内堆放了 32 张牌。
现在将 'pile' 替换为 'xor',将 'cards' 替换为 'bits',将 'hands' 替换为处理器的性能。在 5 次移位和异或运算中,你得到一个数字 xor-ed 的 32 位,如果数字具有偶校验则为 0,否则为 1。
我在 Whosebug 上找到了一段代码并根据需要对其进行了编辑。来源: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
每一步合并两个位集 L 和 R,这样 L 的奇偶校验与 R 的合并。 R 最终具有与 L+R 最初相同的奇偶校验。
在第 1 步中,我们取 8 位并生成一个与 8 位奇偶校验相同的 4 位数字。在第 2 步中,我们生成一个与 4 具有相同奇偶性的 2 位数字。在最后一步中,我们生成一个与 2 具有相同奇偶性的 1 位数字。这意味着在三个步骤中我们得到一个具有相同奇偶性的位奇偶校验为原来的 8.
让我一步一步地告诉你我的意思。
先说第一步,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 保持 奇数.
第二步,L为左2位(10),R为右2位(11)。
xxxxxx11 (R) xxxxxx10 (L) -------- xxxxxx01 (L^R)
现在 6 位被 x 掉了。我们只关心每个数字的两位。
这次L是奇数,R是偶数。结合起来,L+R 是奇数,所以这次我们需要翻转 R 的奇偶性。 R ^= L 这样做吗?同样,确实如此。 L 设置了奇数位,因此异或运算将翻转 R 的奇数位,确保 R 的奇偶校验被切换。 R 变为 奇数.
最后一步,L和R各1位。
xxxxxxx1 (L) xxxxxxx0 (R) -------- xxxxxxx1 (L^R)
L 为 1,R 为 0。就像前面的步骤一样,我们希望 R ^= L 是奇数,事实也是如此。 R 为 奇数.
太棒了。我们从具有奇校验的 8 位开始,通过成功地将两半合并在一起,我们得到了具有相同奇校验的 1 位。
我想提出一个比喻,可能会给出一些直觉:
想象一下,您面前有 4 张卡片,您需要将它们堆叠起来。作为一个有 2 只手的人,您可以每只手同时拿起一张牌并将它们放在另外 2 只手上,然后拿起其中一对放在另一只手上。
这将在 2 步内堆放 4 张牌。
现在假设您需要堆放 32 张牌并且有 16 手牌(或更多)。您可以使用相同的技巧:创建 16 堆每张 2 张牌、8 堆每张 4 张牌、4 堆每张 8 张牌、2 堆每张 16 张牌,最后是单堆每张 32 张牌。
这在 5 步内堆放了 32 张牌。
现在将 'pile' 替换为 'xor',将 'cards' 替换为 'bits',将 'hands' 替换为处理器的性能。在 5 次移位和异或运算中,你得到一个数字 xor-ed 的 32 位,如果数字具有偶校验则为 0,否则为 1。