什么算法能最快地返回一个数的幂,也就是2的幂
What is the fastest algorithm to return the power of a number which is a power of 2?
给定n = 2^k,我怎么能找到k假设n是32位整数使用C/c++位?
GCC有__builtin_clz
,它在x86/x64上转换为BSR,在ARM上转换为CLZ等,如果硬件不实现它,它会模拟指令。
Visual c++ 2005及以上版本有_BitScanReverse
维基百科写了如何使用位运算符:
/**
* Returns the floor form of binary logarithm for a 32 bit integer.
* −1 is returned if ''n'' is 0.
*/
int floorLog2(unsigned int n) {
if (n == 0)
return -1;
int pos = 0;
if (n >= 1<<16) { n >>= 16; pos += 16; }
if (n >= 1<< 8) { n >>= 8; pos += 8; }
if (n >= 1<< 4) { n >>= 4; pos += 4; }
if (n >= 1<< 2) { n >>= 2; pos += 2; }
if (n >= 1<< 1) { pos += 1; }
return pos;
}
代码取自:维基百科上:二进制对数此页已被更改,原始版本的代码样本仍然可以找到她:维基百科上:二进制对数(2011年5月24日)
您可以使用二进制指数显式存储在浮点数中的事实:
unsigned log2(unsigned x)
{
float f = x;
memcpy(&x, &f, sizeof x);
return (x >> 23) - 127;
}
我不知道这有多快,而且它肯定不是最便携的解决方案,但我觉得它很有趣。
为了好玩,这里有一个完全不同的,相对简单的解决方案:
unsigned log2(unsigned x)
{
unsigned exp = 0;
for (; ;)
{
switch (x)
{
case 128: ++exp;
case 64: ++exp;
case 32: ++exp;
case 16: ++exp;
case 8: ++exp;
case 4: ++exp;
case 2: ++exp;
case 1: return exp;
case 0: throw "illegal input detected";
}
x >>= 8;
exp += 8;
}
}
这是一个完全展开的解决方案:
#define CASE(exp) case (1 << (exp)) : return (exp);
unsigned log2(unsigned x)
{
switch (x)
{
CASE(31) CASE(30) CASE(29) CASE(28)
CASE(27) CASE(26) CASE(25) CASE(24)
CASE(23) CASE(22) CASE(21) CASE(20)
CASE(19) CASE(18) CASE(17) CASE(16)
CASE(15) CASE(14) CASE(13) CASE(12)
CASE(11) CASE(10) CASE( 9) CASE( 8)
CASE( 7) CASE( 6) CASE( 5) CASE( 4)
CASE( 3) CASE( 2) CASE( 1) CASE( 0)
default: throw "illegal input";
}
}
继续右移n的值,直到你得到get 1。计算需要右移的次数
对于可移植的解决方案(不诉诸于特定于实现的东西),您可以使用二进制截断,这可能是不涉及不可移植的东西的最有效的方法之一。例如,假设您的整数为8位:
// Given n = 2^k, k >= 0, returns k.
unsigned int getK (unsigned int n) {
if (n <= 8) {
if (n <= 2) {
if (n == 1) return 0;
return 1;
}
if (n == 4) return 2;
return 3;
}
if (n <= 32) {
if (n == 16) return 4;
return 5;
}
if (n == 64) return 6;
return 7;
}
随着整数大小的增加,这会变得有点笨拙,但你只需要写一次:-)
给定0 <= n <= 2**32
,即0 <= k <= 32
和k可以用一个字节表示。2**32字节的内存通常不会太大,所以最快的计算方法可能是简单的表查找。
如果你使用GCC,我猜这是最快的方法:
int ilog2(int value) {
return 31 - __builtin_clz(value);
}
其中__builtin_clz是一个优化的GCC内置函数
相关文章:
- 在计算中使用二的幂有多有利可图
- 有效地将大数存储为 2 的幂用于路径问题
- 计算 O(1) 中的幂函数
- 查找数字是否为 2 的幂的时间复杂度
- C++在不使用pow或循环的情况下计算一个数字的幂
- 使用用户定义的函数查找数字的幂时出现问题
- 在 NDK 上编译两个带有 gradle 的项目,其中一个依赖于另一个的二进制文件
- 将对象从一个 std::d eque 移动到另一个的更好方法
- 仅在 2 的幂上错过了 clang 中的优化
- 确定来自给定数字集的数字中的任何一个的最有效方法是零
- 10的幂的表查找
- 虽然这个简单的 C++ 程序可以打印 2 的幂,但它有很多问题时可以工作
- 一个整数的log2,该整数是2的幂
- 更好的算法来检查一个数字是否既不是素数也不是单个素数的幂
- 我怎样才能从 n 得到一个提高到自身等于 n 的幂的数字?
- 在抛出 std::bad_alloc 实例后终止调用.使用两个类,一个带有指向另一个的指针
- 长整数不适用于 8 的幂C++
- 使用C++计算一个非常大的幂
- 将一个数字除以 2 的幂
- 在有效时间内将一个正整数写成2的幂的和的方法总数