Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/318.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 计算一个数字中的设定位数_Python_Algorithm_Bit Manipulation - Fatal编程技术网

Python 计算一个数字中的设定位数

Python 计算一个数字中的设定位数,python,algorithm,bit-manipulation,Python,Algorithm,Bit Manipulation,问题陈述是: 写一个有效的程序来计算整数二进制表示中的1的个数 我发现了一篇关于这个问题的帖子,其中概述了在logn时间内运行的多种解决方案,包括briankernigan的算法和gcc\uu内置的popcount方法 一个没有提到的解决方案是python方法:binn.count1 这也达到了同样的效果。此方法是否也在log n time中运行?您正在将整数转换为字符串,这意味着它必须生成n个“0”和“1”字符。然后使用str.count,它必须访问字符串中的每个字符才能对“1”字符进行计数

问题陈述是:

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

我发现了一篇关于这个问题的帖子,其中概述了在logn时间内运行的多种解决方案,包括briankernigan的算法和gcc\uu内置的popcount方法

一个没有提到的解决方案是python方法:binn.count1
这也达到了同样的效果。此方法是否也在log n time中运行?

您正在将整数转换为字符串,这意味着它必须生成n个“0”和“1”字符。然后使用str.count,它必须访问字符串中的每个字符才能对“1”字符进行计数

总的来说,您有一个ON算法,具有相对较高的固定成本

请注意,这与链接到的代码的复杂性相同;整数n有logn个位,但算法仍然必须进行n=logn步来计算位数。因此,binn.count'1'算法是等效的,但速度很慢,因为首先生成字符串的成本很高

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


无论测试编号的位长度如何,每个字节的速度总是慢一个百分比。

您正在将整数转换为字符串,这意味着它必须产生N个“0”和“1”字符。然后使用str.count,它必须访问字符串中的每个字符才能对“1”字符进行计数

总的来说,您有一个ON算法,具有相对较高的固定成本

请注意,这与链接到的代码的复杂性相同;整数n有logn个位,但算法仍然必须进行n=logn步来计算位数。因此,binn.count'1'算法是等效的,但速度很慢,因为首先生成字符串的成本很高

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


不管测试数的位长如何,每个字节总是慢一个百分比。

假设您正在尝试计算n的设置位数。在Python的典型实现中,bin将在Olog n时间内计算二进制表示形式,count将遍历字符串,因此导致总体Olog n复杂性


然而,请注意,通常情况下,算法的输入参数是输入的大小。当您处理整数时,这对应于它们的对数。这就是为什么说当前算法具有线性复杂度——变量为m=logn,复杂度为Om。

假设您正在尝试计算n的设定位数。在Python的典型实现中,bin将在Olog n时间内计算二进制表示形式,count将遍历字符串,因此导致总体Olog n复杂性


然而,请注意,通常情况下,算法的输入参数是输入的大小。当您处理整数时,这对应于它们的对数。这就是为什么说当前算法具有线性复杂度——变量为m=logn,复杂度为Om。

它按时运行,其中n是位的总数。不太可能。高效的解决方案是专门为计数位设计的,但是计数函数对任何字符串都进行操作,并且不能使用这些优化,至少不能按时使用。.count1必须访问每个位。宾恩也是线性的吗?@Robᵩ 但根据二进制的定义,binn中有logn位representation@loremIpsum1771我会和面试官讨论你的想法。一般来说,重要的是你的思维过程,而不是你是否记住了最有效的计数位的方法。它会准时运行,其中n是位的总数。不太可能。高效的解决方案是专门为计数位设计的,但是计数函数对任何字符串都进行操作,并且不能使用这些优化,至少不能按时使用。.count1必须访问每个位。宾恩也是线性的吗?@Robᵩ 但根据二进制的定义,binn中有logn位representation@loremIpsum1771我会和面试官讨论你的想法。一般来说,重要的是你的思维过程,而不是你是否记住了最有效的计算位的方法。但是binn中有logn字符。因此,count将适用于Olenbinn=Ologn@DmitryTorba:是的,我已经在那里编辑了一篇解释;链接的文章相当虚伪,因为那里的算法同样是线性的;仅仅因为整数n有logn个比特,并不能使计算比特数的算法突然变成对数。所以计数方法将是线性的,因为创建和附加到字符串的时间将逐渐占主导地位?而且,由于存在logn位,本文中的算法不是仍然是logn吗?@MartijnPieters在我的测试中,您的表方式始终比binn.count'1'方式慢很多。。。大字符串大约慢1.3倍,短字符串大约慢2.6倍,即使我在计时之前准备表格。@Stefa
我自己没有做任何性能测试,因为时间不够,所以我很感激在那里付出的努力。您测试的整数有多大?切换到endianness的“big”有什么区别吗?但是binn中有logn字符。因此,count将适用于Olenbinn=Ologn@DmitryTorba:是的,我已经在那里编辑了一篇解释;链接的文章相当虚伪,因为那里的算法同样是线性的;仅仅因为整数n有logn个比特,并不能使计算比特数的算法突然变成对数。所以计数方法将是线性的,因为创建和附加到字符串的时间将逐渐占主导地位?而且,由于存在logn位,本文中的算法不是仍然是logn吗?@MartijnPieters在我的测试中,您的表方式始终比binn.count'1'方式慢很多。。。大字符串大约慢1.3倍,短字符串大约慢2.6倍,即使在我提前准备表格时也是如此。@StefanPochmann我自己没有做任何性能测试,因为时间不够,所以我很感激在那里所做的努力。您测试的整数有多大?换成“大”表示endianness会有什么不同吗?我不知道这是线性的。如果输入大小为m表示有m位,并且m可以通过log n位找到,其中n是数字的十进制表示形式,那么运行时不应该是logn吗?Loremlpusum171:运行时是一个Ologn,也是一个Om。当我们说一个算法是线性的、二次的或对数的,而不精确变量时,默认的是输入的大小。这里是m,不是n。如果说这个算法是对数的,那就意味着它的复杂度是一个Ologm,即一个Ologlogn。哦,好的,我想我明白你的意思了。那么最好只说算法是线性的,以避免误解?loremlpsum1771:如果你谈话的人知道这个规则,是的,事实上,它来自算法时间复杂度的理论意义。但是现在很多人都在犯这样的错误,所以我认为在日常生活中指出你的算法复杂性的最安全的方法是精确你的变量的含义,例如,我在计算n的位数,我的算法有一个Olog n的时间复杂度。我不确定我是否理解它是线性的。如果输入大小为m表示有m位,并且m可以通过log n位找到,其中n是数字的十进制表示形式,那么运行时不应该是logn吗?Loremlpusum171:运行时是一个Ologn,也是一个Om。当我们说一个算法是线性的、二次的或对数的,而不精确变量时,默认的是输入的大小。这里是m,不是n。如果说这个算法是对数的,那就意味着它的复杂度是一个Ologm,即一个Ologlogn。哦,好的,我想我明白你的意思了。那么最好只说算法是线性的,以避免误解?loremlpsum1771:如果你谈话的人知道这个规则,是的,事实上,它来自算法时间复杂度的理论意义。但是现在很多人都在犯这样的错误,所以我认为在日常生活中指出算法复杂性的最安全的方法是精确计算变量的含义,例如,我在计算n的位数,而我的算法的时间复杂性为Olog n。
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')))
>>> 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