C中的比特扭曲 - 计数比特

时间:2012-03-05 21:18:01

标签: c bit-manipulation bitcount

我想计算在极大位向量(即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 超过位数组起始位置的任意位数。

我知道还有其他计算位数的方法,但是现在我想确定在对其他方法进行比较之前我可以优化这种方法。

4 个答案:

答案 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扩展提供了更多的硬件支持 - 可能还有其它东西可供使用!