【发布时间】:2012-07-07 17:51:17
【问题描述】:
一个很棒的编程资源 Bit Twiddling Hacks 提出 (here) 以下方法来计算 32 位整数的 log2:
#define LT(n) n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n
static const char LogTable256[256] =
{
-1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
LT(4), LT(5), LT(5), LT(6), LT(6), LT(6), LT(6),
LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7)
};
unsigned int v; // 32-bit word to find the log of
unsigned r; // r will be lg(v)
register unsigned int t, tt; // temporaries
if (tt = v >> 16)
{
r = (t = tt >> 8) ? 24 + LogTable256[t] : 16 + LogTable256[tt];
}
else
{
r = (t = v >> 8) ? 8 + LogTable256[t] : LogTable256[v];
}
并提到
查表法只需要大约7次操作即可找到日志 一个 32 位的值。如果扩展到 64 位数量,则需要 大约 9 次操作。
但是,遗憾的是,没有提供任何额外信息,说明应该采用哪种方式将算法扩展到 64 位整数。
关于这种 64 位算法的外观有什么提示吗?
【问题讨论】:
-
@dbaupp 我有一袋
ifs 的所有可能种类、种类和口味,哪一个最好? -
这只是一个学术问题,对吧?否则只需使用
_BitScanReverse64(msvc) 或__builtin_clzll(gcc) -
你已经拥有的那些。 (使用最简单的扩展,它看起来像
if (tt = v >> 48) { ... } else if (tt = v >> 32) { ... } ...,尽管这会比正确的二分搜索 Kendall 正确建议的效果稍差。) -
@harold:不,这根本不是学术问题。即使有人决定使用特定于编译器的 intrisinc,他们也会进入特定于编译器的
#if分支。当然,这并不能消除或多或少普遍实现的“默认”分支的需要。 -
@AndreyT 如果人们开始这样做会很有趣。代码实际上可能成为现实生活中可移植的,而不是 Ivory-Tower 可移植(不能依赖 int 的合理实现,但 gcc 特定的语言扩展可以)
标签: c 64-bit bit-manipulation 32bit-64bit lookup