在没有查找表的情况下计算大数字的位长

时间:2017-07-30 09:17:09

标签: c++ bit-manipulation logarithm

我需要计算floor(log2(n)),其中n是最多64位的正整数。

floor(log2(n))等于n的位长减1,因此标题。

我已实现以下功能:

uint8_t floorLog2(uint64_t n)
{
    uint8_t res = 0;

    uint64_t ONE = 1;
    for (uint8_t k = 32; k > 0; k >>= 1)
    {
        if (n >= (ONE << k))
        {
            n >>= k;
            res |= k;
        }
    }

    return res;
}

效果很好,但是......

我已经意识到,对于6位数字,它的效率低于直接的方法:

uint8_t floorLog2(uint64_t n)
{
    uint8_t res = 0;

    while (n > 1)
    {
        n >>= 1;
        res += 1;
    }

    return res;
}

所以我创建了一个组合版本:

uint8_t floorLog2(uint64_t n)
{
    uint8_t res = 0;

    if (n < 64)
    {
        while (n > 1)
        {
            n >>= 1;
            res += 1;
        }
    }
    else
    {
        uint64_t ONE = 1;
        for (uint8_t k = 32; k > 0; k >>= 1)
        {
            if (n >= (ONE << k))
            {
                n >>= k;
                res |= k;
            }
        }
    }

    return res;
}

但我不喜欢这里的分支(if / else)。

由于我多次调用此函数,因此会影响程序的整体性能。

我在这里缺少更好的方法吗?

任何想到你的想法都会受到赞赏。

谢谢。

1 个答案:

答案 0 :(得分:0)

uint8_t floorLog2(uint64_t n)
{
    uint8_t res = 0;
    static const uint64_t ONE = 1;
    for (uint8_t k = 128; n >= 64; k >>= 1)
    {
        if (n >= (ONE << k))
        {
            n >>= k;
            res |= k;
        }
    }
    while (n > 1)
    {
        n >>= 1;
        res += 1;
    }
    return res;
}