判断一个数是否为2的次幂
判断一个数是否2的次幂的方法:
(n & n - 1) == 0
因为如果一个数是2的次幂,则它对应的二进制数中只有一个1, 如果将这个数减1,则这个仅有的1会变成0,而它的低位则会变成1。所以,将这个数与减去1的数进行与运算后就会为0。
unsigned int IsPowerOfTwo(unsigned int n)
{
if ((n & n-1) == 0) {
return 1;
}
return 0;
}
计算大于或等于某个值的最小的2次幂
问题:计算大于或等于某个值的最小的2次幂。比如给定一个数12,则输出16。给定5、6、7,则会输出8。给定1,则输出1(1是2的0次幂)。
下面是两种常规的做法:
方法一:
#define MAX_POW_TWO (((size_t) 1) << 31)
unsigned int NextPowerOfTwo(unsigned int n)
{
if (n >= MAX_POW_TWO) {
return MAX_POW_TWO;
}
if (n <= 1) {
return 1;
}
unsigned int result = 1;
while (1) {
if (result >= n) {
return result;
}
result <<= 1;
}
}
方法二:
unsigned int NextPowerOfTwo1(unsigned int n)
{
if (n >= MAX_POW_TWO) {
return MAX_POW_TWO;
}
if (n <= 1) {
return 1;
}
unsigned int i = 0;
for (--n; n > 0; n >>= 1) {
i++;
}
return 1 << i;
}
今天看到另外一种算法,感觉很高级。这里记录一下。
方法三:
unsigned int upper_pow_two(unsigned int n)
{
if (n >= MAX_POW_TWO)
return MAX_POW_TWO;
if (n <= 1)
return 1;
n--;
n |= n >> 1;
n |= n >> 2;
n |= n >> 4;
n |= n >> 8;
n |= n >> 16;
n++;
return n;
}
求某个值离它最近的2的次幂
那如果不是求大于或等于这个数的2的次幂,而是求它离的最近的数呢? 比如10, 第一个小于它的数是8,第一个大于它的数是16。因为8离10更近,所以输出是8.那这个算法该怎么写呢?其实稍微修改上面的函数即可:
unsigned int nearestPowerOfTwo(unsigned int n)
{
if (n >= MAX_POW_TWO)
return MAX_POW_TWO;
if (n <= 1)
return 1;
int v = n;
v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v++; // v++之后就是大于这个数的2的次幂
int x = v >> 1; // x是小于这个数的2的次幂
return (v - n) > (n - x) ? x : v;
}