快速了解bitvector计算奇偶校验的方法

时间:2014-02-27 08:15:44

标签: c bitvector

我在C中使用bitvectors。我的bitvectors是unsigned long long。对于大量的向量,我需要知道奇偶校验,即1的位数是偶数还是奇数。

确切的价值并不重要,只是平价。我想知道是否有比计算1的数量和检查更快的东西。我试着想办法,却找不到任何东西。

我希望如何工作的简短示例:

void checkIntersection(unsigned long long int setA, unsigned long long int setB){
    if(isEven(setA & setB)){
        //do something
    }
}

3 个答案:

答案 0 :(得分:3)

采用分而治之的技术:

uint64_t a = value;
a ^= (a >> 32);            // Fold the 32 MSB over the 32 LSB
a ^= (a >> 16);            // reducing the problem by 50%
a ^= (a >> 8);             // <-- this can be a good break even point
..
return lookup_table[a & 0xff];  // 16 or 256 entries are typically good
..

折叠程序可以应用到最后:

a ^= (a >> 1);
return a & 1;

在IA中,可以在缩减为8位后直接检索奇偶校验标志。

a ^= (a >> 4);提出了另一个停止划分的好处,因为某些处理器架构可以提供嵌入到XXM(或NEON)寄存器中的并行查找表uint8_t LUT[16]。或者简单地说,256条入口LUT的潜在高速缓存未命中可以简单地超重一轮额外的计算任务。在给定的架构中,自然最好测量哪种LUT尺寸是最佳的。

最后一个表实际上只包含16位,可以使用以下序列进行模拟:

return ((TRUTH_TABLE_FOR_PARITY) >> (a & 15)) & 1;

上面魔术常量的位 N 编码奇偶校验(N)的布尔值。

答案 1 :(得分:1)

您可以在数组中预先计算一个字节中所有可能的位组合的奇偶校验:

bool pre[256] = { 0, 1, 1, 0, 1, ....}

当您需要找到更大数组的奇偶校验时,您只需:

bool parity (long long unsigned x)
{   
    bool parity = 0;
    while(x)
    {   
        parity ^= pre[x&0xff];
        x>>=8;
    }
    return parity;
}

免责声明:我没有测试过代码,这只是一个想法。

答案 2 :(得分:0)

非常简单。像

这样的东西
unsigned population(unsigned long long x) {
  x = ((x >> 1) & 0x5555555555555555) + (x & 0x5555555555555555);
  x = ((x >> 2) & 0x3333333333333333) + (x & 0x3333333333333333);
  x = ((x >> 4) & 0x0f0f0f0f0f0f0f0f) + (x & 0x0f0f0f0f0f0f0f0f);
  x = (x >> 8) + x;  // Don't need to mask, because 64 < 0xff
  x = (x >> 16) + x;
  x = (x >> 32) + x;
  return x & 0xff;
}

应该有效。此外,一些CPU有人口统计指令(我不认为x86会这样做)。

如果你喜欢这种东西,你应该查看Henry S. Warren,Jr。 Hacker's Delight 这本书。