【发布时间】:2014-06-09 09:57:36
【问题描述】:
我需要在 Linux 内核编程中找到任意数量的 log(base2)。 此操作是否有任何内置功能? 如果不是怎么计算呢?
【问题讨论】:
标签: c linux linux-kernel linux-device-driver
我需要在 Linux 内核编程中找到任意数量的 log(base2)。 此操作是否有任何内置功能? 如果不是怎么计算呢?
【问题讨论】:
标签: c linux linux-kernel linux-device-driver
如果整数结果对你来说足够了,你可以多次除以 2。类似
int logFunc(unsigned int x)
{
int log = -1;
while(x) {
log++;
x >>= 1;
}
return log;
}
如果您需要 fp 操作,您应该阅读以下内容:
[...]如果问题是“我可以在内核中使用 FP”,那么 答案仍然是一个响亮的 NO,因为其他架构可能不会 完全支持。
Linus
另外,您可以查看:Use of floating point in the Linux kernel
编辑:如果您需要更快的版本,您可以阅读Bit Twiddling Hacks - By Sean Eron Anderson
uint32_t v; // find the log base 2 of 32-bit v
int r; // result goes here
static const int MultiplyDeBruijnBitPosition[32] =
{
0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31
};
v |= v >> 1; // first round down to one less than a power of 2
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
r = MultiplyDeBruijnBitPosition[(uint32_t)(v * 0x07C4ACDDU) >> 27];
【讨论】:
>> 对设置为 1 的 unsigned int 的最大位进行二进制搜索。
根据定义,数字 N 在任何特定底数 B 中的对数等于 log(N)/log(B),其中 log() 可以是自然对数(底数 e)或任何其他底数(例如底数 10) ,只要 log(N) 和 log(B) 都是针对相同的基数计算的。
【讨论】: