Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fast way to find exponent of nearest superior power of 2

If I have a number a, I want the value of x in b=2^x, where b is the next power of 2 greater than a.

In case you missed the tag, this is Java, and a is an int. I'm looking for the fastest way to do this. My solution thusfar is to use bit-twiddling to get b, then do (int)(log(b)/log(2)), but I feel like there has to be a faster method that doesn't involve dividing two floating-point numbers.

like image 941
Andy Shulman Avatar asked Mar 09 '11 07:03

Andy Shulman


5 Answers

What about a == 0 ? 0 : 32 - Integer.numberOfLeadingZeros(a - 1)? That avoids floating point entirely. If you know a is never 0, you can leave off the first part.

like image 55
Jeremiah Willcock Avatar answered Oct 30 '22 00:10

Jeremiah Willcock


If anyone is looking for some "bit-twiddling" code that Andy mentions, that could look something like this: (if people have better ways, you should share!)

    public static int nextPowerOf2(final int a)
    {
        int b = 1;
        while (b < a)
        {
            b = b << 1;
        }
        return b;
    }
like image 43
xbakesx Avatar answered Oct 30 '22 01:10

xbakesx


Not necessarily faster, but one liner:

int nextPowerOf2(int num)
{
    return num == 1 ? 1 : Integer.highestOneBit(num - 1) * 2;
}
like image 25
Chipopo Lagoral Avatar answered Oct 30 '22 00:10

Chipopo Lagoral


If you need an answer that works for integers or floating point, both of these should work:

I would think that Math.floor(Math.log(a) * 1.4426950408889634073599246810019) + 1 would be your best bet if you don't want to do bit twiddling.

If you do want to bit-twiddle, you can use Double.doubleToLongBits(a) and then just extract the exponent. I'm thinking ((Double.doubleRawToLongBits(a) >>> 52) & 0x7ff) - 1022 should do the trick.

like image 1
Gabe Avatar answered Oct 30 '22 01:10

Gabe


just do the following:

extract the highest bit by using this method (modified from hdcode):

int msb(int x) {
   if (pow2(x)) return x;
   x = x | (x >> 1);
   x = x | (x >> 2);
   x = x | (x >> 4);
   x = x | (x >> 8);
   x = x | (x >> 16);
   x = x | (x >> 24);
   return x - (x >> 1);
}

int pow2(int n) {
   return (n) & (n-1) == 0;
}

combining both functions into this function to get a number 'b', that is the next power of 2 of a given number 'a':

int log2(int x) {
    int pow = 0;
    if(x >= (1 << 16)) { x >>= 16; pow +=  16;}
    if(x >= (1 << 8 )) { x >>=  8; pow +=   8;}
    if(x >= (1 << 4 )) { x >>=  4; pow +=   4;}
    if(x >= (1 << 2 )) { x >>=  2; pow +=   2;}
    if(x >= (1 << 1 )) { x >>=  1; pow +=   1;}
    return pow;
}

kind regards, dave

like image 1
dave Avatar answered Oct 30 '22 00:10

dave