【发布时间】:2018-09-23 13:19:49
【问题描述】:
与在字符串中计数的内置函数相比,Brian Kernighan 的算法在 python 中计数的性能存在巨大差异,这让我感到惊讶。
在我看来,转换为字符串然后计数是个坏主意。
现在看起来一个坏主意是在寻找性能时循环而不使用内置函数。
import random
x = random.randint(0,1<<1000000)
def count_ones(number):
c = 0
while(number !=0 ):
number = number&(number-1)
c = c + 1
return c
%timeit bin(x).count("1")
%timeit count_ones(x)
5.09 ms ± 20 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
25 s ± 544 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
【问题讨论】:
-
我可能很想这样做:
sum(x & (1 << n) > 0 for n in range(x.bit_length()))....不确定性能如何... -
在 CPython 中,内置函数在机器代码中,而想要运行 Python 需要运行整个解释器,因此使用内置函数通常比实现自定义算法更快。即使如果编译成机器代码它们会更快。在 PyPy 上运行时它们可能会更快。
-
如果你有 Python 3.6+,
def bincount_f(n): return f'{n:b}'.count("1")比bincount_fmt稍快,但仍然比bin(n).count("1")慢。 -
或者
sum(1 for n in range(x.bit_length()) if x & (1 << n))更明智一些... -
但这还不是全部。您的算法实际上具有关于数字表示大小的二次时间,因此它对于 bigints 仍然无效。
标签: python algorithm performance loops built-in