对于给定的x < 10^15
,快速准确地确定最大整数p
,使得2^p <= x
以下是我尝试过的一些方法:
首先,我尝试了这个,但它对大数字不准确:
>>> from math import log
>>> x = 2**3
>>> x
8
>>> p = int(log(x, 2))
>>> 2**p == x
True
>>> x = 2**50
>>> p = int(log(x, 2))
>>> 2**p == x #not accurate for large numbers?
False
我可以试试这样的:
p = 1
i = 1
while True:
if i * 2 > n:
break
i *= 2
p += 1
not_p = n - p
如果p是50,这将需要50次操作
我可以预先计算2的所有幂,直到2^50,然后使用二进制搜索来找到p。这将需要大约log(50)的操作,但似乎有点过分和丑陋?
我找到了这个基于C的解决方案的线程:Compute fast log base 2 ceiling
然而,它似乎有点丑陋,我不太确定如何将其转换为Python。
7条答案
按热度按时间jtjikinw1#
在Python〉= 2.7中,你可以使用整数的
.bit_length()
方法:它给出了
wwodge7n2#
你在注解中指定x是一个整数,但是对于任何来到这里的人来说,他们的x已经是一个float,那么**math.frexp()**在提取以2为底的日志时会非常快:
C function that frexp() calls只是抓取和调整指数。更多的解释:
[1]
是因为frexp()返回一个元组(有效数,指数)。-1
说明有效位在[0.5,1.0)范围内。例如,250存储为0.5x251。2^p <= x
,所以是p == floor(log(x,2))
。(来源于another answer)
30byixjq3#
注意!接受的答案返回
floor(log(n, 2))
,而不是像问题标题所暗示的那样返回ceil(log(n, 2))
!如果你来这里是为了一个clog 2的实现,请这样做:
为了完整:
tct7dpnv4#
你可以尝试numpy中的
log2
函数,它似乎适用于高达2^62的幂:除此之外(至少对我来说),由于numpy的内部数字类型的限制,它失败了,但它将处理你所说的范围内的数据。
gdrx4gfi5#
对我来说,OSX 10.7上的Python 2.6.5(CPython)很好用:
它至少对指数1e9仍然有效,到那时它开始需要相当长的时间来做数学运算。在测试中,
x
和p
实际上得到了什么?你运行的是什么版本的Python,在什么操作系统上?4ioopgfo6#
关于“对大数字不准确”,你在这里的挑战是浮点表示确实没有你需要的那么精确(
49.999999999993 != 50.0
)。好消息是,C例程的转换非常简单:
另一种方法是,你可以四舍五入到最接近的整数,而不是截断:
5cnsuln77#
我需要计算2的上界幂(计算出使用模运算符在给定范围内生成一个随机数需要多少字节的熵)。
从一个粗略的实验中,我认为下面的计算给出了最小整数p,使得瓦尔〈2^p
它可能和你能得到的一样快,并且只使用按位整数运算。
对于给定的n,您的稍微不同的值将通过以下方式计算
...也许吧。但无论如何,按位算术可以给予你一个如何快速完成这个操作的线索。