一种计算比特奇偶校验的简单/按位方法

时间:2015-10-29 17:31:30

标签: algorithm bit-manipulation

在我的情况下,奇偶校验定义为:

相邻的0,1排列的数量,使所有0在左边,所有1都在右边。

请注意,不计算1,1的排列和0,0的排列。当排列的数量是偶数时,则奇偶校验被称为偶数,否则它是奇数。

一些例子:

'101'奇数

'1000'奇数

'10011'甚至

'10100'奇数

1 个答案:

答案 0 :(得分:3)

首先,请注意,相邻0-1排列的最小数量是inversions的数量:它是0-1对的数量,0表示1的右边。

令( Ki )是所有设置位的排序顺序(即,位等于1)。位置从零开始计数,从右计数(即从低位开始)。然后在 i - 设置位( i 从零开始计数)右侧有 Ki - i 零位。因此,在所有设置位上,反转的总数是 sum(Ki) - sum(i)

第一部分易于处理。如果 Ki 是偶数,请丢弃它。如果 Ki 为奇数,则切换总和的奇偶校验。因此实际上 sum(Ki)的奇偶校验等于奇数位置中的设置位数的奇偶校验。可以很容易地找到这个数字:首先屏蔽所有偶数位,然后计算设置位数(popcount)。

第二部分也很容易处理。首先,计算您的号码中的设置位数(再次使用popcount)。让它成为 n 。现在 k = 0..n-1 k 的总和恰好是(n-1)* n / 2 。请注意,当且仅当数字 n 中的第二位(从此处的1开始计数)被设置时,它才是奇数。因此,只要您获得 n ,您只需要提取其第二位。

以下是C ++中生成的代码:

uint32_t get_inversions_parity(uint32_t x) {
    uint32_t bitsCnt = popcount(x);
    uint32_t oddCnt = popcount(x & 0xAAAAAAAAU);
    return ((bitsCnt >> 1) ^ oddCnt) & 1;
}

如你所见,你只需要一些快速的方法来做popcount。