【问题标题】:Calculating bit-length of large numbers without lookup tables在没有查找表的情况下计算大数的位长
【发布时间】:2017-07-30 09:17:08
【问题描述】:

我需要计算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)。

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

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

【问题讨论】:

  • “计算前导零”,您会发现许多重复项。
  • 这是最好在硬件中完成的事情。您的uint256_t 是如何定义的?它是某些 CPU 的本机类型,还是使用多个较小的本机整数实现的?你用的是什么CPU?这需要便携吗?
  • “需要遵循语言标准”和“uint256_t 是原生类型”有点矛盾。
  • floor(log2(n)) 的直接方法不是floor(log2(n))吗?
  • 查看示例,从 graphics.stanford.edu/~seander/bithacks.html#IntegerLogLookup 开始。此链接上的代码示例都假定为 32 位无符号,但在大多数情况下将它们调整为 64 位无符号应该是直截了当的。

标签: c++ bit-manipulation logarithm


【解决方案1】:
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;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-24
    • 1970-01-01
    • 2022-10-13
    相关资源
    最近更新 更多