python - 计算数字中设置位的数量

标签 python algorithm bit-manipulation

问题陈述是:

编写一个高效的程序来计算整数二进制表示中 1 的个数。

我找到了关于这个问题的帖子 here其中概述了以 log(n) 时间运行的多个解决方案,包括 Brian Kernigan 的算法和 gcc __builtin_popcount() 方法。

一个没有提到的解决方案是 python 方法:bin(n).count("1") 这也达到了同样的效果。这个方法是否也运行了 log n 次?

最佳答案

您正在将整数转换为字符串,这意味着它必须生成 N 个 '0''1' 字符。然后您使用 str.count(),它必须访问字符串中的每个字符 以计算 '1' 个字符。

总而言之,您有一个 O(N) 算法,具有相对较高的恒定成本。

请注意,这与您链接到的代码的复杂性相同;整数 n 有 log(n) 位,但算法仍然需要执行 N = log(n) 步来计算位数。因此,bin(n).count('1') 算法是等效的,但,因为首先生成字符串的成本很高。

以表格为代价,您可以转向处理整数每字节:

table = [0]
while len(table) < 256:
    table += [t + 1 for t in table]

length = sum(map(table.__getitem__, n.to_bytes(n.bit_length() // 8 + 1, 'little')))

但是,因为 Python 需要生成一系列新对象(一个 bytes 对象和几个整数),所以此方法的速度永远无法击败 bin(n).count( '1') 方法:

>>> from random import choice
>>> import timeit
>>> table = [0]
>>> while len(table) < 256:
...     table += [t + 1 for t in table]
...
>>> def perbyte(n): return sum(map(table.__getitem__, n.to_bytes(n.bit_length() // 8 + 1, 'little')))
...
>>> def strcount(n): return bin(n).count('1')
...
>>> n = int(''.join([choice('01') for _ in range(2 ** 16)]))
>>> for f in (strcount, perbyte):
...     print(f.__name__, timeit.timeit('f(n)', 'from __main__ import f, n', number=1000))
...
strcount 1.11822146497434
perbyte 1.4401431040023454

无论测试数的位长如何,perbyte 总是慢一个百分比。

关于python - 计算数字中设置位的数量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39301375/

相关文章:

java - 遍历由边表示的树

algorithm - 贪心算法

c++ - 解释下面的C++方法

ruby - 清除 Ruby 中的所有其他位

python - 如何更新在 ubuntu 上部署在 uWSGI 和 Nginx 上的 flask API 代码?

python - pandas 在 to_latex 时用任意数字替换 NAN

javascript - “no ' Access-Control-Allow-Origin ' header is present” Cherrypy 错误

找到最少的矩形以覆盖一组矩形而不重叠的算法

bit-manipulation - 什么是常见位运算的长版本?

python - 良好风格的控制台输入