log2的幂为2的整数

时间:2017-11-02 11:24:51

标签: c++ algorithm math logarithm

是否有一种有效的方法来查找数字的log2,假设它是2的幂。我知道显而易见的方法,比如有一张桌子或

for (log2=0;x!=1;x>>=1,log2++);

但我想知道是否有更高效/更优雅的方式。

2 个答案:

答案 0 :(得分:11)

您可以只计算前导或尾随零位的数量,因为任何精确的2次幂都表示为单个1位,其他所有位为0.许多CPU都有执行此操作的特殊指令,以及编译器等因为gcc具有这些操作的内在函数,它们被编译为适当体系结构上的单个指令。

如果你有一个有效的clz(“计数前导零”),那么log2实现可能如下所示:

int32_t ilog2(uint32_t x)
{
    return sizeof(uint32_t) * CHAR_BIT - clz(x) - 1;
}

(注意:ilog2(0)返回-1。)

使用gcc或兼容gcc的编译器时,您可以像这样定义clz

#define clz(x) __builtin_clz(x)

微软有类似的东西:BitScanReverse

请注意,计算尾随零(使用ctz指令)似乎更方便,但a clz instruction is more widely available on different CPU architectures

使用clz而非ctz的另一个好处是,您获得floor(log2(x))非幂2值,使您的ilog2函数更加普遍有用比如果你使用ctz,那只适用于精确的2次幂。

另请参阅:Finding the first set bit in a binary number

答案 1 :(得分:1)

我没有对此进行基准测试,但它应该运行得相当快,因为​​它不需要多次迭代:

int which_power_of_2(uint64_t x) {
    uint64_t z = 0x0000000100000000ULL;
    int p = 31, d = 16;
    while (d) {
        if (x & (z-1)) {
            p -= d;
            z >>= d;
        }
        else {
            p += d;
            z <<= d;
        }
        d >>= 1;
    }
    return x ? ((x & z) ? p+1 : p) : -1;
}