C中的位计数类似于bit twiddling hack

时间:2012-04-10 16:27:45

标签: c bit-manipulation counter bit

我需要创建一个例程来计算一个不涉及循环的字中的位(只有位操作),并且不使用大常量。

int x = 0xFFFFFFFF;
x += (~((x >> 1) & 0x55555555)+1);
x = (((x >> 2) & 0x33333333) + (x & 0x33333333));
x = (((x >> 4) + x) & 0x0F0F0F0F);
x += (x >> 8);
x += (x >> 16);
return(x & 0x0000003F);

这是我发现的有点乱七八糟的黑客,但我可以使用的最大常数是0xFF ...不知道如何做到这一点。

谢谢大家。

3 个答案:

答案 0 :(得分:4)

例如,您可以使用常量数组COUNTS[16],它是0到15之间数字的二进制表示中的设置位数。然后:

static inline int byte_count (int x) {
  static const int COUNTS[16] = { 0, 1, 1, 2, 1, /* fill in the rest manually */ };
  return COUNTS[x & 15] + COUNTS[x >> 4];
}

int count(int x) {
  return byte_count(x >> 24) + byte_count((x >> 16) & 255) + byte_count((x >> 8) & 255) + byte_count(x & 255);
}

没有循环,没有大于255的常量。

答案 1 :(得分:3)

使用您的算法:

int x = 0xFF;
x |= (x << 8);  // x = 0xFFFF
x |= (x << 16); // x = 0xFFFFFFFF

然后是代码的其余部分 - 只要它有效。

递归解决方案:

int foo ( int x )
{
    if ( x == 0 )
        return 0;
    return (x & 1) + foo ( x/2 );
}

答案 2 :(得分:0)

您的问题已经回答here

int NumberOfSetBits(int i)
{
    i = i - ((i >> 1) & 0x55555555);
    i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
    return (((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
}