Convierta a binario y mantenga ceros a la izquierda en Python

154

Estoy tratando de convertir un entero a binario usando la función bin () en Python. Sin embargo, siempre elimina los ceros iniciales, que realmente necesito, de modo que el resultado sea siempre de 8 bits:

Ejemplo:

bin(1) -> 0b1

# What I would like:
bin(1) -> 0b00000001

¿Hay alguna forma de hacer esto?

Niels Sønderbæk
fuente
Ver también: ¿ Python int a binario? , especialmente mi respuesta con la representación de n bits. No es exactamente lo mismo, pero llegué a esta pregunta buscando mi respuesta ...
Martin Thoma

Respuestas:

219

Usa la format()función :

>>> format(14, '#010b')
'0b00001110'

La format()función simplemente formatea la entrada siguiendo el mini idioma de Especificación de formato . La #hace que el formato incluye el 0bprefijo, y el 010tamaño formatea la salida para caber en 10 caracteres de ancho, con 0material de relleno; 2 caracteres para el 0bprefijo, los otros 8 para los dígitos binarios.

Esta es la opción más compacta y directa.

Si coloca el resultado en una cadena más grande, use un literal de cadena con formato (3.6+) o use str.format()y coloque el segundo argumento para la format()función después de los dos puntos del marcador de posición {:..}:

>>> value = 14
>>> f'The produced output, in binary, is: {value:#010b}'
'The produced output, in binary, is: 0b00001110'
>>> 'The produced output, in binary, is: {:#010b}'.format(value)
'The produced output, in binary, is: 0b00001110'

De hecho, incluso para formatear un solo valor (sin poner el resultado en una cadena más grande), usar un literal de cadena formateado es más rápido que usar format():

>>> import timeit
>>> timeit.timeit("f_(v, '#010b')", "v = 14; f_ = format")  # use a local for performance
0.40298633499332936
>>> timeit.timeit("f'{v:#010b}'", "v = 14")
0.2850222919951193

Pero lo usaría solo si el rendimiento en un circuito cerrado es importante, ya que format(...)comunica mejor la intención.

Si no desea el 0bprefijo, simplemente suelte #y ajuste la longitud del campo:

>>> format(14, '08b')
'00001110'
Martijn Pieters
fuente
3
Exactamente lo que estaba buscando, este formato es realmente útil para mí. Empecé a aprender la manipulación de bits y busqué en Google el formato de bits para números en Python. Encontró esto. Gracias.
kratostoical
Funciona bien Sin embargo, puede volverse un poco voluminoso. format(192,'08b')+'.'+format(0,'08b')+'.'+format(2,'08b')+'.'+format(33,'08b') 11000000.00000000.00000010.00100001
voces
@ tjt263: Es por eso que explícitamente afirmo que si está colocando el resultado en una cadena más grande, use un literal de cadena con formato (3.6+) o use str.format()y ponga el segundo argumento para la función format () después de los dos puntos del marcador de posición {:..}:
Martijn Pieters
1
@ tjt263: por ejemplo, uso f"{192:08b}.{0:08b}.{2:08b}.{33:08b}".
Martijn Pieters
Muy agradable. Nunca hubiera sabido que a eso te referías solo con una explicación. Pero ahora que he visto tu ejemplo, probablemente nunca lo olvidaré. Salud.
voces
115
>>> '{:08b}'.format(1)
'00000001'

Ver: Especificación de formato Mini-idioma


Nota para Python 2.6 o anterior, no puede omitir el identificador de argumento posicional antes :, así que use

>>> '{0:08b}'.format(1)
'00000001'      
bwbrowning
fuente
3
No hay necesidad de usar str.format()aquí cuando format()lo hará. Te falta el 0bprefijo.
Martijn Pieters
2
@MartijnPieters, str.formates más flexible que format()porque te permitirá hacer múltiples variables a la vez. Sigo olvidando que la formatfunción incluso existe. Es cierto que es perfectamente adecuado en este caso.
Mark Ransom
1
@MarkRansom: Exactamente, cuando solo usa str.format()un solo {}elemento, ningún otro texto, no usa plantillas de cadenas, está formateando un valor . En ese caso solo úsalo format(). :-)
Martijn Pieters
30

estoy usando

bin(1)[2:].zfill(8)

imprimirá

'00000001'
rekinyz
fuente
9

Puede usar el mini idioma de formato de cadena:

def binary(num, pre='0b', length=8, spacer=0):
    return '{0}{{:{1}>{2}}}'.format(pre, spacer, length).format(bin(num)[2:])

Manifestación:

print binary(1)

Salida:

'0b00000001'

EDITAR: basado en la idea de @Martijn Pieters

def binary(num, length=8):
    return format(num, '#0{}b'.format(length + 2))
Peter Varo
fuente
2
Se puede usar el mismo lenguaje de formato para incluir el prefijo. Uso #. También existe format(), lo que le ahorra tener que hacer una plantilla de cadena completa.
Martijn Pieters
2

Cuando se usa Python >= 3.6, la forma más limpia es usar cadenas f con formato de cadena :

>>> var = 23
>>> f"{var:#010b}"
'0b00010111'

Explicación:

  • var la variable a formatear
  • : todo después de esto es el especificador de formato
  • #usa la forma alternativa (agrega el 0bprefijo)
  • 0 almohadilla con ceros
  • 10pad a una longitud total de 10 (esto incluye los 2 caracteres para 0b)
  • b usar representación binaria para el número
ruohola
fuente
No, no es el más limpio, no a menos que haga más con la cadena que un solo marcador de posición . De lo contrario, format(var, "#010b")comunica la intención mucho mejor. Sin embargo, es la opción más rápida. Pero eso ya lo sabes, porque ya cubro todo lo que publicaste en mi respuesta.
Martijn Pieters
1

A veces solo quieres un revestimiento simple:

binary = ''.join(['{0:08b}'.format(ord(x)) for x in input])

Python 3

marca
fuente
1
Tenga en cuenta que [ ]no debería ser necesario: join()acepta una expresión generadora. ''.join('{0:08b}'.format(ord(x)) for x in input)
Christoph Burschka
@ChristophBurschka nota que debido a que str.join()necesita hacer dos pases, una entrada del generador se convierte primero en una lista antes de unirse. Esto tiene un costo en el rendimiento y es realmente mejor pasar una comprensión de la lista en lugar de una expresión generadora. Es uno si son excepciones a la regla.
Martijn Pieters
-1

Puedes usar algo como esto

("{:0%db}"%length).format(num)
Adán
fuente
2
Al menos use el bloque de código para su fragmento de código. Y si realmente quiere que sea una buena respuesta, también agregue algunos comentarios sobre por qué esta solución está resolviendo la pregunta OP.
β.εηοιτ.βε
No necesita usar un estilo de formato de cadena diferente solo para agregar un ancho variable. Simplemente agregue otro marcador de posición:"{:0{l}b}".format(num, l=length)
Martijn Pieters
-1

puede usar el método de cadena rjust de la sintaxis de python: string.rjust (length, fillchar) fillchar es opcional

y para tu pregunta puedes escribir así

'0b'+ '1'.rjust(8,'0)

entonces será '0b00000001'

Jaydeep Mahajan
fuente
Hay un error de sintaxis. Pero lo que es más importante, no responde a la pregunta, que se trata de convertir una inta su representación binaria textual; Ni siquiera empiezas con un int.
Thierry Lathuille
-3

Puedes usar zfill:

print str(1).zfill(2) 
print str(10).zfill(2) 
print str(100).zfill(2)

huellas dactilares:

01
10
100

Me gusta esta solución, ya que ayuda no solo al generar el número, sino también cuando necesita asignarlo a una variable ... por ejemplo, x = str (datetime.date.today (). Month) .zfill (2) will devuelve x como '02' para el mes de febrero.

Anshul Garg
fuente
1
El problema con zfill es que trata la cadena binaria como una cadena y agrega los ceros antes del indicador binario 'b' ... por ejemplo, bin(14) da '' 0b1110 '' y bin(14).zfill(8) da '' 000b1110 '' no '' 0b00001110 '', que es lo que se desea
Shaun