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

Calculating bit-length of large numbers without lookup tables

本文关键字:计算 情况下 查找      更新时间:2023-10-16

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

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

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

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;
}
相关文章: