在Python中查找大于或等于n的2的最小幂
在Python中,返回大于或等于给定非负整数的最小2次方的最简单函数是什么 例如,大于或等于6的2的最小幂是8。总是返回在Python中查找大于或等于n的2的最小幂,python,Python,在Python中,返回大于或等于给定非负整数的最小2次方的最简单函数是什么 例如,大于或等于6的2的最小幂是8。总是返回2**(x-1)。bit_length()是不正确的,因为尽管它为x=1返回1,但为x=0返回非单调的2。对于x=0,单调安全的简单修复是: def next_power_of_2(x): return 1 if x == 0 else 2**(x - 1).bit_length() 样本输出: >>> print(', '.join(f'{x}
2**(x-1)。bit_length()
是不正确的,因为尽管它为x=1返回1,但为x=0返回非单调的2。对于x=0,单调安全的简单修复是:
def next_power_of_2(x):
return 1 if x == 0 else 2**(x - 1).bit_length()
样本输出:
>>> 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
>>> 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
>>> 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
可以迂腐地说,x=0应该返回0(而不是1),因为
2**float('-inf')==0
这对您有用吗:
import math
def next_power_of_2(x):
return 1 if x == 0 else 2**math.ceil(math.log2(x))
请注意,math.log2
在Python3中可用,但在Python2中不可用。使用它而不是math.log
可以避免后者在2**29及以上的数值问题
样本输出:
>>> 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
>>> 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
>>> 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
可以迂腐地说x=0应该返回0(而不是1),因为2**float('-inf')==0
让我们测试一下:
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)
对于Python.org Python 3.3.0:
6.566169916652143: power_bit_length
3.098236607853323: shift_bit_length
9.982460380066186: power_log
使用pypy 1.9.0/2.7.2:
2.8580930233: power_bit_length
2.49524712563: shift_bit_length
3.4371240139: power_log
我相信这表明2**
是这里的慢部分;使用bit_length
而不是log
确实可以加快速度,但使用1
对于16位整数。我们可以使用位操作如下所示:
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
要进一步阅读,请参阅。嗯,我知道这个问题很老,我的答案也很简单,但我真的很惊讶一直没有人把它贴在这里,所以我会把它作为答案贴出来
最简单的解决方案非常简单,不需要导入任何库,如果在使用的同时使用
语句,就可以在一个循环中完成
所以逻辑非常简单,创建一个值为1的变量,当变量的值小于数字时,将变量乘以2
代码:
这可以很容易地修改,以计算下一个电源柜到其他一些基准:
def nextpower(num, base):
i = 1
while i < num: i *= base
return i
def nextpower(num,base):
i=1
而i
对于大型x
,速度不是很慢吗?除此之外,我不能说我理解它。@delnan——你为什么认为这会很慢?(我也不理解代码…@delnan:First,bit_length
实际上是log base 2向上舍入-1,并且非常快。所以,把2提高到它的幂,你就完成了。也许做1我不确定python是如何实现位长度的,但即使是对于x
的巨大值,它也几乎是即时的。不过,我认为这是将2取到x-1
的第次方,然后取位长度。其实情况正好相反。这样,中间整数会很快变大,但这样更合理。仍然不是我所说的直观。需要日志,我认为这比较慢。@jhoyla性能很少相关(缓慢的部分是查找两个函数并调用它们,而不是专门调用log
)。这肯定更具可读性和明显性(至少对我来说)。唯一能确定它是否更慢的方法是测试…但它确实有缺点,它说next\u-power\u-of-two(0)
是一个DomainError
而不是1…@jhoyla:哦,说得好。每个版本都有一个简单的修复程序,但我不确定哪一个版本在修复后看起来更清晰…(另外,next\u power\u of_two(0)也是有争议的)
应该是0
,而不是1
,因为0
是-inf
的第次幂,因此也是-inf+1
的第次幂…但是无论哪种方式,2
显然是错误的。)请注意,x==0
的结果是不正确的,因为(-1)。位长度()==1
在Python中。请注意准确性math.log(2**29,2)
为29.000000000000004,因此power\u log(2**29)
给出了错误的答案30。@ColonelPanic如果使用math.log2
,您注意到的问题就不存在了,这是理所当然的。只有在使用math.log
的情况下,问题才从29岁开始存在。比特旋转黑客非常棒,但请引用来源
def nextpower(num, base):
i = 1
while i < num: i *= base
return i