找到2的整数次幂的2的对数

时间:2016-02-16 19:21:07

标签: c bit-manipulation

我遇到了这一堆,似乎应该有更好的方法来做到这一点。我想用bit twiddling来完成与以下内容相同的事情:

uint8_t nextlog(uint32_t n) {
  return (uint8_t) ceil(log2(n)) + 1;
}

使用示例:

nextlog(0) -> undefined
nextlog(1) == 1
nextlog(3) == 3  // 0b11 -{next power 2}-> 0b100 -{log2+1}-> 3
nextlog(32) == 6 // 0b00100000 -{log2+1}-> 6
nextlog(71) == 8 // 0b01000111 --> 0b10000000 -> 8

我提出的最好的方法是将众所周知的bit twiddling hacks引用中的“舍入到下一个最高2的幂”和“查找整数的整数对数2”组合起来。我认为值得注意的是__builtin_clz可以帮助完成问题的后半部分。

2 个答案:

答案 0 :(得分:2)

你想要32 - clz(x),尽管你声称相反。

你声称log 2 0b100是3,这是数学中的错误。正确的答案是2。

它不在" bit twddling hacks"页面,但我发现了这个:

int clz(uint32_t x) {
    x |= x >> 1;
    x |= x >> 2;
    x |= x >> 4;
    x |= x >> 8;
    x |= x >> 16;
    return 32 - popcount(x);
}

int popcount(uint32_t x) {
    x = x - ((x >> 1) & 0x55555555);
    x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
    return (((x + (x >> 4)) & 0x0f0f0f0f) * 0x01010101) >> 24;
}

请注意,与x86上的ffs相比,我确信性能有点糟糕。

请参阅:http://aggregate.org/MAGIC/#Leading%20Zero%20Count

答案 1 :(得分:0)

根据@Mark Dickinson的评论,单个分支的明显解决方案如下:

uint8_t nextlog(uint32_t n) {
  if (n == 1) return 1;
  return 33 - __builtin_clz(n - 1);
}