dmz*_*rsk 27 python binary iterator
让我们a=109
或1101101
二进制.如何迭代此数字的位,例如:[64, 32, 8, 4, 1]
Dun*_*can 46
只需要从二进制表示中获取1,而不必迭代所有介入的0,这是一个技巧:
def bits(n):
while n:
b = n & (~n+1)
yield b
n ^= b
>>> for b in bits(109):
print(b)
1
4
8
32
64
Run Code Online (Sandbox Code Playgroud)
Win*_*ert 10
我的方法:
def bits(number):
bit = 1
while number >= bit:
if number & bit:
yield bit
bit <<= 1
Run Code Online (Sandbox Code Playgroud)
我不认为它有内置函数.
我也想知道对你所做的事情是否有更好的方法.很有可能你真的不想迭代这样的位.他们可能是一个更好的方式.
出于好奇,我在这里发布的方法上运行了一些时间,我的结果:
Winston 2.35238099098
F.J. 6.21106815338
F.J. (2) 5.21456193924
Sven 2.90593099594
Duncan 2.33568000793
freegnu 4.67035484314
Run Code Online (Sandbox Code Playgroud)
FJ转换成一个字符串,我猜这会伤害他的表现.各种优化尝试都有所帮助,但不足以让Sven产生与其他人相反的情况,如果您确实需要它,这可能是一个优势.邓肯的进攻获胜速度(几乎没有)
再次使用340282366920938463463374607431768211457而不是109:
Winston 44.5073108673
F.J. 74.7332041264
Sven 47.6416211128
Duncan 2.58612513542
Run Code Online (Sandbox Code Playgroud)
很好,邓肯!应该注意的是,对于Duncan的方法来说,这几乎是最好的情况,所以它不会总是具有这种戏剧性的优势.
>>> [2**i for i, v in enumerate(bin(109)[:1:-1]) if int(v)]
[1, 4, 8, 32, 64]
Run Code Online (Sandbox Code Playgroud)
显然这里的顺序是相反的,您可以使用它或反转结果:
>>> [2**i for i, v in enumerate(bin(109)[:1:-1]) if int(v)][::-1]
[64, 32, 8, 4, 1]
Run Code Online (Sandbox Code Playgroud)
编辑:这是一个稍长的版本,应该更有效:
from itertools import takewhile, count
[p for p in takewhile(lambda x: x <= 109, (2**i for i in count())) if p & 109]
Run Code Online (Sandbox Code Playgroud)