Vamos a a=109
o 1101101
en binario. ¿Cómo puedo iterar sobre bits de este número, por ejemplo: [64, 32, 8, 4, 1]
Manera pitónica de iterar sobre los bits del número entero
Respuesta
Hay un truco para conseguir justo de la 1 de la representación binaria sin tener que iterar sobre todo del 0 intervenir:
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
Mi enfoque:
def bits(number):
bit = 1
while number >= bit:
if number & bit:
yield bit
bit <<= 1
No creo que hay una función incorporada para ello.
También me pregunto si no hay un mejor enfoque para lo que sea que esté haciendo. Hay muchas posibilidades de que realmente no desee iterar sobre los bits como este. Pueden ser una forma mucho mejor.
Por curiosidad me corrió un poco de tiempo en los métodos publicada aquí, mis resultados:
Winston 2.35238099098
F.J. 6.21106815338
F.J. (2) 5.21456193924
Sven 2.90593099594
Duncan 2.33568000793
freegnu 4.67035484314
F. J. convierte en una cadena, supongo que perjudica a su actuación. Los diversos intentos de optimización ayudan, pero no lo suficiente, Sven produce el revés de todos los demás, lo que podría ser una ventaja si realmente lo necesitabas. El enfoque de Duncan gana speedwise (a duras penas)
De nuevo con 340282366920938463463374607431768211457 en lugar de 109:
Winston 44.5073108673
F.J. 74.7332041264
Sven 47.6416211128
Duncan 2.58612513542
Niza, Duncan! Cabe señalar que este es el mejor caso para el método de Duncan, por lo que no siempre tendrá esta ventaja dramática.
Python 2.7:
def binary_decomposition(x):
p = 2 ** (int(x).bit_length() - 1)
while p:
if p & x:
yield p
p //= 2
Ejemplo:
>>> list(binary_decomposition(109))
[64, 32, 8, 4, 1]
>>> [2**i for i, v in enumerate(bin(109)[:1:-1]) if int(v)]
[1, 4, 8, 32, 64]
Obviamente, el orden se invierte aquí, se podía ya sea sólo tiene que utilizar este o revertir el resultado:
>>> [2**i for i, v in enumerate(bin(109)[:1:-1]) if int(v)][::-1]
[64, 32, 8, 4, 1]
edit: Aquí es una versión ligeramente más largo que debería ser más eficiente:
from itertools import takewhile, count
[p for p in takewhile(lambda x: x <= 109, (2**i for i in count())) if p & 109]
+1 for oneliner –
La conversión de cadenas es más rápida que la versión del iterador en el peor de los casos 340282366920938463463374607431768211457 y tal vez algo más de un cierto tamaño. Cambié tu prueba if int() en una prueba de cadena == '1' para acelerar las cosas. @ Duncan todavía lo golpea con facilidad aunque. – freegnu
La eficiencia de la respuesta de FJ se puede mejorar de manera espectacular.
from itertools import count,takewhile
[2**i for i in takewhile(lambda x:109>2**x,count()) if 109&2**i][::-1]
me gusta trazadores de líneas uno :)
I hicieron un timeit.Timer.timeit rápida() en contra de este y @Duncan. Duncan aún gana pero no el delineador está al menos en la misma clase.
from timeit import Timer
duncan="""\
def bits(n):
while n:
b=n&(~n+1)
yield b
n^=b
"""
Duncan=Timer('list(bits(109))[::-1]',duncan)
Duncan.timeit()
4.3226630687713623
freegnu=Timer('[2**i for i in takewhile(lambda x:109>2**x,count()) if 109&2**i][::-1]','from itertools import count,takewhile')
freegnu.timeit()
5.2898638248443604
Ejemplo solución de una línea:
[1 << bit for bit in xrange(bitfield.bit_length()) if bitfield & (1 << bit)]
O:
[bit for bit in (1 << n for n in xrange(bitfield.bit_length())) if bitfield & bit]
Notas:
- uso gama en Python 3
- pensar acerca de la comprobación bitfie ld es> = 0
S.O. no me deja poner esto como un comentario, pero aquí hay un ejemplo línea por línea de cómo funciona la solución Duncan's. Espero que esto aclare lo que está pasando.
Usemos el número decimal 109 como un ejemplo:
# 109 is .............. 0110 1101
# ~109 is -110 which is 1001 0010 NOTE: It's -110 instead of -109 because of 1's compliment
# ~109+1 is -109....... 1001 0011
# 109 AND ~109 is...... 0000 0001 = 1 <---- 1st value yielded by the generator
# 109 XOR 1 is......... 0110 1100 = n = 108
# 108.................. 0110 1100
# ~108+1= -108......... 1001 0100
# 108 AND -108......... 0000 0100 = 4 <---- 2nd value yielded by the generator
# 108 XOR 4............ 0110 1000 = n = 104
# 104.................. 0110 1000
# ~104+1............... 1001 1000
# 104 AND -104......... 0000 1000 = 8 <---- 3rd value yielded by the generator
# 104 XOR 8............ 0110 0000 = n = 96
# 96................... 0110 0000
# ~96+1................ 1010 0000
# 96 AND -96........... 0010 0000 = 32 <---- 4th value yielded by the generator
# 96 XOR 32............ 0100 0000 = n = 64
# 64................... 0100 0000
# ~64+1................ 1100 0000
# 64 AND -64........... 0100 0000 = 64 <---- 5th value yielded by the generator
# 64 XOR 64............ 0000 0000 = n = 0; thus, the while loop terminates.
- 1. Manera pitónica de iterar sobre una matriz 3D
- 2. ¿Manera eficiente de iterar sobre bits verdaderos en std :: bitset?
- 3. Manera pitónica de iterar sobre una instancia de collections.Counter() en orden descendente?
- 4. Inversión de bits del número entero de Python
- 5. ¿Iterar sobre los diccionarios VBA?
- 6. generar aleatoria de 64 bits número entero
- 7. C++: ¿Es seguro comparar un número entero de 64 bits con un número entero de 32 bits?
- 8. Manera pitónica de poblar la matriz numpy
- 9. Contar el número de bits puestos en un entero
- 10. los bits inversa en número
- 11. Cómo iterar sobre los niños por bucle
- 12. Looping a través de bits en un número entero, ruby
- 13. Entero a byte con un número dado de bits establecidos
- 14. Iterar sobre los atributos del objeto en python
- 15. buscando la parte del número entero de un número
- 16. ¿Contar el número de bits en un entero de 64 bits (largo, grande)?
- 17. Iterar sobre enum?
- 18. Iterar sobre todos los valores dobles posibles
- 19. jquery iterar sobre elementos secundarios
- 20. SQL que obtiene los dos últimos dígitos del número entero
- 21. Manera pitónica de acceder al elemento arbitrario del diccionario
- 22. ¿Hay alguna manera de iterar sobre un diccionario?
- 23. Convertir entero a una representación de bits
- 24. manera pitónica de convertir la variable a la lista
- 25. ¿Cómo cuento el número de bits cero en un número entero?
- 26. Manera pitónica de importar módulos de paquetes
- 27. iterar sobre la tupla
- 28. Crear listas de listas de manera pitónica
- 29. Manera pitónica de copiar un objeto iterable
- 30. R iterar sobre columnas trama de datos
http://wiki.python.org/moin/BitwiseOperators debería ser suficiente –
Si usted está buscando un número que puede utilizar la conversión 'bin (109)' o 'int ('1101101', 2)'. –
'map (lambda x: int (x), bin (NUMBER) [2:])'. Pero esta solución es probablemente demasiado fácil y antiponética. ;) – Gandaro