简体   繁体   English

C ++ 2的最大功效<= n

[英]C++ largest power of 2 <= n

How do I calculate the largest power of two <= some number n? 如何计算两个<=某个数字n的最大幂?

Right now I am using floor(log(n)/log(2)+.05) but it doesn't seem to be reliable for all n. 现在我正在使用floor(log(n)/ log(2)+。05),但对于所有n来说似乎都不可靠。 Is there anything a little cleaner / not at the mercy of rounding errors? 有没有什么更清洁的东西/不舍入四舍五入的错误?

I assume that the number is unsigned. 我认为这个数字是无符号的。 You can use the knowledge of the binary representation. 您可以使用二进制表示形式的知识。

That number will be the number with 1 at same MSB position and with all zero. 该数字将是在相同MSB位置上为1且全为零的数字。

Following loop will help you. 以下循环将为您提供帮助。

do {
    y = x;
    x = x&(x-1);
}while(x);
return y;

where x is the original number and the y is the result. 其中x是原始数字, y是结果。

Branch free code is given below. 分支免费代码如下。

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);
}

or (counting on loop unrolling, which all modern compilers can do) 或(依靠循环展开,所有现代编译器都可以做到)

unsigned log2(unsigned x)
{
  for (int i = 0; i < std::numeric_limits<unsigned>::digits; i*=2)
     x |= (x>>i);
  return x - (x>>1);
}

Source: Hacker's Delight. 资料来源:黑客的喜悦。

I'm not entirely sure which integral type you're targeting, so at the behest of trying to cover them all... 我不确定您要定位的是哪种整数类型,因此请尝试覆盖所有整数类型...

#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;
}

Output 输出量

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

In binary (assuming you have an integral type) the largest power of 2 is the Most Significant Bit 在二进制文件中(假设您具有整数类型),2的最大幂是最高有效位

There are several ways to calculate this efficiently 有几种方法可以有效地进行计算

the most efficent is to use a built-in that uses machine code that can execute in one cycle 最有效的方法是使用内置的机器代码,该机器代码可以在一个周期内执行

the least efficient is to loop through removing the lowest bit 效率最低的是通过删除最低位来循环

Here is one I like if you can't use built-ins: 如果您不能使用内置功能,这是我喜欢的功能:

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];
  } 
}

you can find more like this at: http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogLookup 您可以在以下位置找到更多类似的信息: http : //graphics.stanford.edu/~seander/bithacks.html#IntegerLogLookup

This test worked for 32 bit signed int where best is assigned the closest power of 2 to the candidate value, x in the domain of 4 to ~2 billion: 这个测试工作了32位在4个领域签署,其中最好的是分配的2最接近电源候选值INT,X到〜2十亿:

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
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM