我要求将k
计算为2的最小幂,即> =整数值,n
(n
始终> 0)
目前我正在使用:
#define log2(x) log(x)/log(2)
#define round(x) (int)(x+0.5)
k = round(pow(2,(ceil(log2(n)))));
这是一个性能关键功能
计算k
是否有更高效的计算方法?
答案 0 :(得分:9)
/* returns greatest power of 2 less than or equal to x, branch-free */
/* Source: Hacker's Delight, First Edition. */
int
flp2(int x)
{
x = x | (x>>1);
x = x | (x>>2);
x = x | (x>>4);
x = x | (x>>8);
x = x | (x>>16);
return x - (x>>1);
}
学习它并了解它是如何工作的,这很有趣。我认为唯一可以让您确定哪种解决方案最适合您的情况的方法是在文本夹具中使用所有这些解决方案并对其进行分析,看看哪种解决方案对您的目的最有效。
无分支,相对于其他一些人而言,这一点可能在性能方面非常好,但你应该直接测试它以确保。
如果你想要2的最小幂大于或等于X,你可以使用稍微不同的解决方案:
unsigned
clp2(unsigned x)
{
x = x -1;
x = x | (x >> 1);
x = x | (x >> 2);
x = x | (x >> 4);
x = x | (x >> 8);
x = x | (x >> 16);
return x + 1;
}
答案 1 :(得分:2)
lim = 123;
n = 1;
while( ( n = n << 1 ) <= lim );
将你的数字乘以2,直到它比lim更大。
左移一个乘以2。
答案 2 :(得分:2)
是的,您可以通过简单地计算相关数字并使用位移来确定2的幂来计算 右移取数字中的所有位并将它们向右移动,丢弃最右边(最不重要)的数字。它等效于执行整数除法2.左移一个值将所有位向左移动,丢弃从左端移位的位,并向右端添加零,有效地将该值乘以2。 因此,如果计算在数字达到零之前需要右移的次数,则计算基数2对数的整数部分。然后使用它来通过多次左移值1来创建结果。
int CalculateK(int val)
{
int cnt = 0;
while(val > 0)
{
cnt++;
val = val >> 1;
}
return 1 << cnt;
}
编辑:或者,更简单一点:您不必计算计数
int CalculateK(int val)
{
int res = 1;
while(res <= val) res <<= 1;
return res ;
}
答案 3 :(得分:2)
int calculate_least_covering_power_of_two(int x)
{
int k = 1;
while( k < x ) k = k << 1;
return k;
}
答案 4 :(得分:1)
k = 1 << (int)(ceil(log2(n)));
您可以利用二进制数字表示2的幂(1为1,10为2,100为4等)的事实。将指数2向左移1会得到相同的值,但速度要快得多。
虽然如果你能以某种方式避开ceil(log2(n)),你会看到更大的性能提升。
答案 5 :(得分:1)
来源:hackersdelight.org
/* altered to: power of 2 which is greater than an integer value */
unsigned clp2(unsigned x) {
x = x | (x >> 1);
x = x | (x >> 2);
x = x | (x >> 4);
x = x | (x >> 8);
x = x | (x >>16);
return x + 1;
}
请记住,您需要添加:
x = x | (x >> 32);
对于64位数字。