Pythonic迭代整数位的方法

dmz*_*rsk 27 python binary iterator

让我们a=1091101101二进制.如何迭代此数字的位,例如:[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的方法来说,这几乎是最好的情况,所以它不会总是具有这种戏剧性的优势.

  • 那个循环条件应该是`number> = bit`. (2认同)

And*_*ark 7

>>> [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)