我在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
}
}
答案 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 这本书。