简体   繁体   English

在 Python 中找到大于或等于 n 的最小 2 次方

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

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?在 Python 中返回大于或等于给定非负整数的最小 2 次幂的最简单函数是什么?

For example, the smallest power of 2 greater than or equal to 6 is 8.例如,大于或等于 6 的 2 的最小次方是 8。

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 .我使用range(1, 1000001)而不是range(1000000)的原因是power_log版本将在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:使用 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:使用 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:使用 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;我相信这表明2**是这里缓慢的部分; using bit_length instead of log does speed things up, but using 1<< instead of 2** is more important.使用bit_length而不是log确实可以加快速度,但是使用1<<而不是2**更为重要。

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. OP 的版本要求您进行心理上下文切换,从对数切换到位,然后再切换回指数。 Either stay in bits the whole time ( shift_bit_length ), or stay in logs and exponents ( power_log ).要么一直保留在位中 ( shift_bit_length ),要么保留在对数和指数中 ( power_log )。

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.总是返回2**(x - 1).bit_length()是不正确的,因为虽然它对 x=1 返回 1,但对 x=0 返回非单调的 2。 A simple fix that is monotonically safe for x=0 is:一个对 x=0 单调安全的简单修复是:

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 .可以迂腐地争论说 x=0 应该返回 0(而不是 1),因为2**float('-inf') == 0

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.请注意, math.log2在 Python 3 中可用,但在 Python 2 中不可用。使用它代替math.log可避免后者在 2**29 及以后出现数值问题。

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 .可以迂腐地争论说 x=0 应该返回 0(而不是 1),因为2**float('-inf') == 0

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 .如需进一步阅读,请参阅此资源

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!最简单的解决方案真的很简单,不需要导入任何库,如果你使用while语句,你可以在一个循环中完成!

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!所以逻辑很简单,创建一个值为1的变量,当变量的值小于number时,将变量乘以2!

Code:代码:

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

The return values for n = 1, 63, 64, 255, 256, 1000, 4095: 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
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.对于 16 位整数。

暂无
暂无

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

相关问题 算法(Python):找到大于k的最小数 - Algorithm (Python): find the smallest number greater than k python 中的“大于”或“等于”与“等于”或“大于” - “Greater than” or “equal” vs “equal” or “greater than” in python Python 给定一个N个整数的数组A,在O(n)时间复杂度内返回A中没有出现的最小正数integer(大于0) - Python given an array A of N integers, returns the smallest positive integer (greater than 0) that does not occur in A in O(n) time complexity 给定一个包含 N 个整数的数组 A,返回在 O(n) 时间复杂度内不会出现在 A 中的最小正 integer(大于 0)(Python Sol) - Given an array A of N integers, returns the smallest positive integer (greater than 0) that does not occur in A in O(n) time complexity (Python Sol) Python:如何在大于M的公共列中找到非零单元格的N行以上 - Python: How to find greater than N rows with non zero cells in greater than M common columns 如何在 or-tools 一维数组(python,or-tools)中找到大于 0 的最小值 - How to find the smallest value greater than 0 in a or-tools 1-D array (python , or-tools ) 在排序列表中查找大于给定数字的最小数字 - Find the smallest number that is greater than a given number in a sorted list 在Python中具有加号,等于号和大于号的表达式 - Expression with plus, equal, and greater than symbols in python 如何使 python 大于/小于或等于? - How to make a greater/less than or equal to on python? 在python 2.7中查找矩阵中每一列等于或大于1时的行号 - Find row number when each column in a matrix is equal to or greater than 1 in python 2.7
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM