如何计算2的最大功率< =某个数字n?
现在我正在使用floor(log(n)/ log(2)+。05)但它似乎并不是所有n都可靠。有没有更清洁的东西/没有舍入错误的摆布?
答案 0 :(得分:3)
我认为这个数字是无符号的。您可以使用二进制表示的知识。
该数字将是1在相同MSB位置并且全部为零的数字。
以下循环可以帮助您。
do {
y = x;
x = x&(x-1);
}while(x);
return y;
其中x
是原始数字,y
是结果。
下面给出了免费分支代码。
unsigned flp2(unsigned 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);
}
或(指望循环展开,所有现代编译器都可以这样做)
unsigned log2(unsigned x)
{
for (int i = 0; i < std::numeric_limits<unsigned>::digits; i*=2)
x |= (x>>i);
return x - (x>>1);
}
来源:Hacker's Delight。
答案 1 :(得分:2)
我不完全确定你所针对的是哪种整体类型,所以在要求全部覆盖它们的要求下......
#include <iostream>
#include <cmath>
template<typename T>
typename std::enable_if<std::is_integral<T>::value,T>::type fn(T N)
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
return T(1) << static_cast<T>(std::floor(std::log2(N)));
}
int main()
{
std::cout << fn(4095) << std::endl;
std::cout << fn(4096) << std::endl;
std::cout << fn(4097) << std::endl;
std::cout << fn(281474976710655) << std::endl;
std::cout << fn(281474976710656) << std::endl;
std::cout << fn(281474976710657) << std::endl;
return 0;
}
<强>输出强>
typename std::enable_if<std::is_integral<T>::value, T>::type fn(T) [T = int]
2048
typename std::enable_if<std::is_integral<T>::value, T>::type fn(T) [T = int]
4096
typename std::enable_if<std::is_integral<T>::value, T>::type fn(T) [T = int]
4096
typename std::enable_if<std::is_integral<T>::value, T>::type fn(T) [T = long]
140737488355328
typename std::enable_if<std::is_integral<T>::value, T>::type fn(T) [T = long]
281474976710656
typename std::enable_if<std::is_integral<T>::value, T>::type fn(T) [T = long]
281474976710656
答案 2 :(得分:1)
在二进制中(假设您有一个整数类型),2的最大幂是最高位
有几种方法可以有效地计算
最有效的是使用内置函数,该内置函数使用可在一个周期内执行的机器代码
效率最低的是循环删除最低位
如果您不能使用内置插件,我喜欢这个:
unsigned int v; // 32-bit value to find the log2 of
const unsigned int b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000};
const unsigned int S[] = {1, 2, 4, 8, 16};
int i;
register unsigned int r = 0; // result of log2(v) will go here
for (i = 4; i >= 0; i--) // unroll for speed...
{
if (v & b[i])
{
v >>= S[i];
r |= S[i];
}
}
你可以在http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogLookup
找到更多这样的内容答案 3 :(得分:0)
此测试适用于32位有符号整数,其中 最佳 被分配给候选值2的最接近幂 x 在4到20亿的范围内:
for (int x = 4; x < (1<<31)-1; x++)
{
int best = (int)(log((double)x)/log(2.0));
int test = (int)pow((double)2, best);
if (test > x || (test*2 <= x && test*2 > 0)) // test*2 < 0 when very large
break; // fail
}