Find the smallest power of 2 greater than or equal to n in Python

Question:

What is the simplest function to return the smallest power of 2 that is greater than or equal to a given non-negative integer in Python?

For example, the smallest power of 2 greater than or equal to 6 is 8.

Asked By: jhoyla

||

Answers:

Always returning 2**(x - 1).bit_length() is incorrect because although it returns 1 for x=1, it returns a non-monotonic 2 for x=0. A simple fix that is monotonically safe for x=0 is:

def next_power_of_2(x):  
    return 1 if x == 0 else 2**(x - 1).bit_length()

Sample outputs:

>>> print(', '.join(f'{x}:{next_power_of_2(x)}' for x in range(10)))
0:1, 1:1, 2:2, 3:4, 4:4, 5:8, 6:8, 7:8, 8:8, 9:16

It can pedantically be argued that x=0 should return 0 (and not 1), since 2**float('-inf') == 0.

Answered By: jhoyla

Would this work for you:

import math

def next_power_of_2(x):
    return 1 if x == 0 else 2**math.ceil(math.log2(x))

Note that math.log2 is available in Python 3 but not in Python 2. Using it instead of math.log avoids numerical problems with the latter at 2**29 and beyond.

Sample outputs:

>>> print(', '.join(f'{x}:{next_power_of_2(x)}' for x in range(10)))
0:1, 1:1, 2:2, 3:4, 4:4, 5:8, 6:8, 7:8, 8:8, 9:16

It can pedantically be argued that x=0 should return 0 (and not 1), since 2**float('-inf') == 0.

Answered By: inspectorG4dget

Let’s test it:

import collections
import math
import timeit

def power_bit_length(x):
    return 2**(x-1).bit_length()

def shift_bit_length(x):
    return 1<<(x-1).bit_length()

def power_log(x):
    return 2**(math.ceil(math.log(x, 2)))

def test(f):
    collections.deque((f(i) for i in range(1, 1000001)), maxlen=0)

def timetest(f):
    print('{}: {}'.format(timeit.timeit(lambda: test(f), number=10),
                          f.__name__))

timetest(power_bit_length)
timetest(shift_bit_length)
timetest(power_log)

The reason I’m using range(1, 1000001) instead of just range(1000000) is that the power_log version will fail on 0. The reason I’m using a small number of reps over a largeish range instead of lots of reps over a small range is because I expect that different versions will have different performance over different domains. (If you expect to be calling this with huge thousand-bit numbers, of course, you want a test that uses those.)

With Apple Python 2.7.2:

4.38817000389: power_bit_length
3.69475698471: shift_bit_length
7.91623902321: power_log

With Python.org Python 3.3.0:

6.566169916652143: power_bit_length
3.098236607853323: shift_bit_length
9.982460380066186: power_log

With pypy 1.9.0/2.7.2:

2.8580930233: power_bit_length
2.49524712563: shift_bit_length
3.4371240139: power_log

I believe this demonstrates that the 2** is the slow part here; using bit_length instead of log does speed things up, but using 1<< instead of 2** is more important.

Also, I think it’s clearer. The OP’s version requires you to make a mental context-switch from logarithms to bits, and then back to exponents. Either stay in bits the whole time (shift_bit_length), or stay in logs and exponents (power_log).

Answered By: abarnert
v+=(v==0);
v--;
v|=v>>1;
v|=v>>2;
v|=v>>4;
v|=v>>8;
v|=v>>16;
v++;

For a 16-bit integer.

Answered By: sudeepdino008

We can do this as follows using bit manipulation:

def next_power_of_2(n):
    if n == 0:
        return 1
    if n & (n - 1) == 0:
        return n
    while n & (n - 1) > 0:
        n &= (n - 1)
    return n << 1

Sample outputs:

>>> print(', '.join(f'{x}:{next_power_of_2(x)}' for x in range(10)))
0:1, 1:1, 2:2, 3:4, 4:4, 5:8, 6:8, 7:8, 8:8, 9:16

For further reading, refer to this resource.

Answered By: Akash Kandpal

Hmm, I know this question is old and my answer is pretty simple, but I am really surprised in all this time nobody posted it here, so I will post it as an answer.

The easiest solution is really simple, no need to import any library, you can do it in one loop if you use while statement!

So the logic is very simple, create a variable with a value of 1, while the value of the variable is less than the number, multiply the variable by 2!

Code:

i = 1
while i < n: i *=2

The return values for n = 1, 63, 64, 255, 256, 1000, 4095:

2, 64, 64, 256, 256, 1024, 4096

This can be easily modified to calculate the next power closet to a number of other bases as well:

def nextpower(num, base):
  i = 1
  while i < num: i *= base
  return i
Answered By: user15290516
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.