C++ 2 的最大幂 <= n
C++ largest power of 2 <= n
如何计算二的最大幂<=一些数字n?
现在我使用的是floor(log(n)/log(2)+0.05),但它似乎对所有n都不可靠。有什么更干净/不受舍入误差影响的吗?
我假设这个数字是无符号的。您可以使用二进制表示的知识。
该数字将是在相同MSB位置具有1且全部为零的数字。
以下循环将对您有所帮助。
do {
y = x;
x = x&(x-1);
}while(x);
return y;
其中CCD_ 1是原始号码,而CCD_。
下面给出了无分支代码。
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。
我不完全确定你要针对的是哪种积分类型,所以在尝试覆盖所有类型的要求下。。。
#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的最大幂是最高有效位
有几种方法可以有效地计算
最有效的方法是使用内置的,它使用可以在一个周期内执行的机器代码
效率最低的是循环去除最低比特的
如果你不能使用内置程序,我喜欢这里的一个:
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
此测试适用于32位有符号int,其中best被分配为与候选值最接近的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
}
相关文章:
- 请解释这句话(cout<<1+int((a<b)^((b-a)&1) )<<endl
- 呼叫运营商<<临时
- 如何防止clang格式在流运算符调用之间添加换行符<<
- <<操作员在下面的行中工作
- 如何显式调用运算符<<
- 模板操作员&lt;未打电话
- C / CUDA中的模板方法是3个角括号(&lt;&lt;&lt;)
- C - 创建矢量&lt; vector&lt; double&gt;&gt;矩阵具有分配而不是inizializ
- 错误:调用"std::vector<:vector<int>>::p ush_back(std::vector<std::__cxx11::basic_string<
- C 建造者Clang STD :: Sill,找不到超载的操作员&lt;
- 为什么STD :: MAP需要操作员&lt;以及我如何写一个
- 为什么“操作员”需要const但不是为“运营商&lt;”
- 为什么将此对向量&lt; map&lt; int,int&gt;&gt;中的地图进行更新.失败
- C :对矢量进行排序&lt; struct&gt;(结构有2个整数)基于结构的整数之一
- 明确的专业化“ CheckIntmap&lt;&gt;”实例化
- 什么是模板&lt;&gt;inline bla bla
- 左角支架解释为操作员&lt;而不是模板参数
- 编辑C Qlist&lt; object*&gt; gt;QML代码和一些QML警告中的模型
- 超载操作员&lt;&lt; - 必须是二进制操作员
- 没有匹配的“运营商&lt;&lt;”