【发布时间】: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