我想计算在极大位向量(即100,000位)中设置的位。
我目前正在做的是使用指向char(即char * cPtr)的指针指向位数组的开头。然后我:
1. look at each element of the array (i.e. cPtr[x]),
2. convert it to an integer (i.e. (int) cPtr[x])
3. use a 256 element look-up table to see how many bits are set in the given byte (i.e. cPtr[x]).
我觉得如果我使用一个短的int指针(即short int * sPtr),那么我只需要一半的查找,但是有一个65534元素的查找表,它会有它的自己的内存使用成本。
我想知道每次检查的最佳位数是多少。此外,如果该数字不是某种预设类型的大小,我该如何向下走我的位向量并将指针设置为 ANY 超过位数组起始位置的任意位数。
我知道还有其他计算位数的方法,但是现在我想确定在对其他方法进行比较之前我可以优化这种方法。
答案 0 :(得分:2)
您可以使用按位运算来计算:
char c = cPtr[x];
int num = ((c & 0x01) >> 0) +
((c & 0x02) >> 1) +
((c & 0x04) >> 2) +
((c & 0x08) >> 3) +
((c & 0x10) >> 4) +
((c & 0x20) >> 5) +
((c & 0x40) >> 6) +
((c & 0x80) >> 7);
它可能看起来有点长,但它不需要访问很多时间来记忆,所以毕竟它对我来说似乎非常便宜。
你甚至可以通过每次读取一个int来降低它,但是你可能需要解决一个对齐问题。
答案 1 :(得分:1)
这应该非常快(取自Wikipedia):
static unsigned char wordbits[65536] = { bitcounts of ints between 0 and 65535 };
static int popcount(uint32 i)
{
return (wordbits[i&0xFFFF] + wordbits[i>>16]);
}
通过这种方式,您可以检查每次迭代32位。
答案 2 :(得分:1)
我想知道每次检查的最佳位数是多少
找出答案的唯一方法是测试。一次查看this question for a discussion of the fastest way to count 32 bits。
另外,如果该数字不是某种预设类型的大小,我该怎么办? 向下走我的位向量并将指针设置为任意数字 位数超过位数组的起始位置。
您无法设置指向任意位的指针。大多数机器都有字节寻址,有些只能寻址字。
你可以构造一个以任意位开头的单词,如下所示:
long wordAtBit(int32_t* array, size_t bit)
{
size_t idx = bit>>5;
long word = array[idx] >> (bit&31);
return word | (array[idx+1] << (32 - (bit&31));
}
答案 3 :(得分:0)
我参加派对有点晚了,但是到目前为止建议的方法要快得多。原因是许多现代架构提供硬件指令以各种方式计数位数(前导零,前导零,尾随零或1,计数设置为1的位数等等)。计算设置为1的位数称为汉明权重,通常也称为人口计数,或者只是popcount。
事实上,x86 CPU具有POPCNT指令作为SSE4.2指令集的一部分。英特尔最新的最新CPU体系结构(昵称为Haswell)为BMI1和BMI2扩展提供了更多的硬件支持 - 可能还有其它东西可供使用!