Python int a cadena binaria?

530

¿Hay algún método de Python enlatado para convertir un entero (o largo) en una cadena binaria en Python?

Hay una gran cantidad de funciones dec2bin () en Google ... Pero esperaba poder usar una función / biblioteca incorporada.

Nate
fuente
Para la toma opuesta, para un algoritmo de procesamiento de cadena puro, vea esto .
CopyPasteIt

Respuestas:

750

El método de formato de cadena de Python puede tomar una especificación de formato.

>>> "{0:b}".format(37)
'100101'

Formato de documentación de especificaciones para Python 2

Formato de documentación de especificaciones para Python 3

Tung Nguyen
fuente
86
str.format()solo formatear un valor es exagerado. Ir directamente a la format()función : format(n, 'b'). No es necesario analizar el marcador de posición y asociarlo a un argumento, vaya directamente a la operación de formateo de valor en sí. Úselo solo str.format()si necesita colocar el resultado formateado en una cadena más larga (por ejemplo, úsela como plantilla).
Martijn Pieters
29
@mike: O use la especificación de formato. Agregue el número de dígitos con una 0cadena a la cadena de formato: format(10, '016b')formatos de 16 dígitos con ceros a la izquierda.
Martijn Pieters
En este caso, el 0en "{0:b}"se puede soltar no? Quiero decir, en el caso de que solo se esté formateando un número, es correcto ponerlo "{:b}", ¿no?
tomasyany
1
normalmente se usaría una representación de 4/8 / ... bit:"{:08b}".format(37)
Sparkler
2
f "{37: b}" en Python3.7 o posterior.
DA
471

Si está buscando bin()como equivalente a hex(), se agregó en python 2.6.

Ejemplo:

>>> bin(10)
'0b1010'
John Fouhy
fuente
66
Tenga en cuenta también que es más rápido str(bin(i))[2:](0.369s para 1000000ops) que "{0:b}".format(i)(0.721s para 1000000ops)
mVChr
64
@mVChr si alguien está convirtiendo números en una representación binaria ASCII, realmente espero que la velocidad no importe.
Nick T
29
@mVChr: str.format()es la herramienta incorrecta de todos modos, en su format(i, 'b')lugar usaría . Tenga en cuenta que eso también le ofrece opciones de relleno y alineación; format(i, '016b')formatear a un número binario de 16 bits con relleno cero. Para hacer lo mismo con bin()usted, debe agregar una str.zfill()llamada: bin(i)[2:].zfill(16)(¡no es necesario llamar str()!). format()La legibilidad y flexibilidad (el formato dinámico es mucho más difícil bin()) son grandes compensaciones, no optimice el rendimiento a menos que sea necesario, hasta entonces optimice la capacidad de mantenimiento.
Martijn Pieters
¿Qué significa [2:]?
zero_cool
44
Por supuesto, con Python 3.6+ ahora puede usar f"{37:b}".
Luke Davis el
63

Python en realidad hace tener algo ya incorporado para esto, la capacidad de hacer operaciones como '{0:b}'.format(42), lo que le dará el patrón de bits (en una cadena) a 42, o 101010.


Para una filosofía más general, ningún idioma o biblioteca dará a su base de usuarios todo lo que desean. Si está trabajando en un entorno que no proporciona exactamente lo que necesita, debe recopilar fragmentos de código a medida que se desarrolla para asegurarse de que nunca tenga que escribir lo mismo dos veces. Como, por ejemplo, el pseudocódigo:

define intToBinString, receiving intVal:
    if intVal is equal to zero:
        return "0"
    set strVal to ""
    while intVal is greater than zero:
        if intVal is odd:
            prefix "1" to strVal
        else:
            prefix "0" to strVal
        divide intVal by two, rounding down
    return strVal

que construirá su cadena binaria basada en el valor decimal. Solo tenga en cuenta que es un poco de pseudocódigo genérico que puede no ser la forma más eficiente de hacerlo, sin embargo, con las iteraciones que parece proponer, no hará mucha diferencia. Realmente solo se entiende como una guía sobre cómo se podría hacer.

La idea general es usar código de (en orden de preferencia):

  • el idioma o las bibliotecas integradas.
  • bibliotecas de terceros con licencias adecuadas.
  • tu propia colección
  • algo nuevo que necesita escribir (y guardar en su propia colección para más adelante).
paxdiablo
fuente
1
Algunos buenos consejos en esta respuesta. Lástima que el código sea innecesariamente lento. Propones un O (N ^ 2) algo donde haría un O (N). La parte problemática está en las líneas s = "1" + sy s = "0" + s. Cada uno hace una copia innecesaria de s. En su lugar, debe invertir la cadena justo antes de devolverla.
Andreas Magnusson
@Andreas, lo que propuse fue usar '{0:b}'.format(42), el método lento fue simplemente un ejemplo de cómo hacerlo genéricamente, que puede ser o no O (n ^ 2) dependiendo del lenguaje real utilizado. Solo se parece a Python, ya que Python es un lenguaje de pseudocódigo ideal, así que lo cambiaré para que quede claro.
paxdiablo
En realidad, sería un lenguaje bastante esotérico donde s = "1" + sno era O (N) cuando ses un tipo de cadena. ¿Quizás un idioma donde todas las cadenas se almacenan al revés o cada carácter es un nodo en una lista vinculada? Para cualquier lenguaje típico, una cadena es básicamente una matriz de caracteres. En ese caso, el prefijo de una cadena requiere que se haga una copia, ¿de qué otra manera va a poner el carácter antes que los otros caracteres?
Andreas Magnusson el
Puedo imaginar fácilmente un tipo de cadena que consiste en un bloque de memoria donde la cadena está justificada a la derecha dentro de ese bloque, y un desplazamiento a su carácter inicial. Para prefijar un carácter, simplemente reduciría el desplazamiento y almacenaría el carácter allí. Sí, eso sería esotérico, pero tiene poco sentido para mí discutir sobre posibles problemas del mundo real con un poco de pseudocódigo, especialmente porque no es probable que tenga más de unas pocas docenas de bits / iteraciones. Incluso el tipo de burbuja muy difamado es adecuado si el tamaño de sus datos es pequeño :-) En cualquier caso, agregaré una nota sobre la eficiencia.
paxdiablo
Claro, si la eficiencia es importante, probablemente no elegirías Python para empezar. Aún así, en mi experiencia, sucede con bastante frecuencia que el código que fue escrito ingenuamente usando un algoritmo O (N²) y probado con un pequeño conjunto de datos se usa rápidamente con un conjunto de datos mucho más grande porque "parece funcionar". Entonces, de repente, tiene un código que demora horas en ejecutarse y que cuando se soluciona puede demorar solo unos segundos. Los algos O (N²) son insidiosos porque parecen funcionar por un tiempo, pero cuando tus datos escalan, no lo hacen y para entonces el tipo que los escribió ha renunciado y nadie sabe por qué las cosas tardan para siempre.
Andreas Magnusson
41

Si desea una representación textual sin el prefijo 0b, puede usar esto:

get_bin = lambda x: format(x, 'b')

print(get_bin(3))
>>> '11'

print(get_bin(-3))
>>> '-11'

Cuando quieres una representación de n bits:

get_bin = lambda x, n: format(x, 'b').zfill(n)
>>> get_bin(12, 32)
'00000000000000000000000000001100'
>>> get_bin(-12, 32)
'-00000000000000000000000000001100'

Alternativamente, si prefiere tener una función:

def get_bin(x, n=0):
    """
    Get the binary representation of x.

    Parameters
    ----------
    x : int
    n : int
        Minimum number of digits. If x needs less digits in binary, the rest
        is filled with zeros.

    Returns
    -------
    str
    """
    return format(x, 'b').zfill(n)
Martin Thoma
fuente
55
O simplemente usar format(integer, 'b'). bin()es una herramienta de depuración, específicamente dirigida a producir la sintaxis literal entera binaria de Python , format()está destinada a producir formatos específicos.
Martijn Pieters
1
@MartijnPieters Muchas gracias por mencionarlo. He ajustado mi solución. ¿Cómo sabe que bin()es una herramienta de depuración destinada a producir la sintaxis literal de enteros binarios de Python? No pude encontrar eso en la documentación.
Martin Thoma
2
De la documentación: El resultado es una expresión Python válida . Su objetivo es producir una expresión de Python, no generar representaciones de usuario final. Lo mismo se aplica a oct()y hex().
Martijn Pieters
44
Más alternativas: si va a hacer que el ancho sea dinámico, en lugar de str.zfill()podría usar str.format()o format()con un segundo argumento dinámico: '{0:0{1}b}'.format(x, n)o format(b, '0{}b'.format(n)).
Martijn Pieters
@MartijnPieters ¡Guau, muchas gracias por este aporte! No sabía que esto era posible con el formato. Sin embargo, creo que mi respuesta actual zfilles más fácil de leer y comprender que el segundo argumento dinámico, por lo que lo guardaré.
Martin Thoma
38

Como una referencia:

def toBinary(n):
    return ''.join(str(1 & int(n) >> i) for i in range(64)[::-1])

Esta función puede convertir un entero positivo tan grande como 18446744073709551615, representado como una cadena '1111111111111111111111111111111111111111111111111111111111111111'.

Se puede modificar para servir un número entero mucho más grande, aunque puede no ser tan útil como "{0:b}".format()o bin().

kctong529
fuente
@GarethDavidson, ¿qué versión es esta? Tener esto declarado explícitamente podría ser de mayor uso en el futuro al buscarlo en Google.
Lobo
Era la versión 2.7, creo. Dudo que funcione en 3.x
Gareth Davidson
17

Una forma sencilla de hacerlo es usar el formato de cadena, consulte esta página .

>> "{0:b}".format(10)
'1010'

Y si desea tener una longitud fija de la cadena binaria, puede usar esto:

>> "{0:{fill}8b}".format(10, fill='0')
'00001010'

Si se requiere el complemento a dos, entonces se puede usar la siguiente línea:

'{0:{fill}{width}b}'.format((x + 2**n) % 2**n, fill='0', width=n)

donde n es el ancho de la cadena binaria.

Xiang
fuente
16

¡Esto es para Python 3 y mantiene los ceros a la izquierda!

print(format(0, '08b'))

ingrese la descripción de la imagen aquí

grepit
fuente
1
Agradezco la respuesta simple.
reergymerej
14

one-liner con lambda :

>>> binary = lambda n: '' if n==0 else binary(n/2) + str(n%2)

prueba:

>>> binary(5)
'101'



EDITAR :

pero entonces :(

t1 = time()
for i in range(1000000):
     binary(i)
t2 = time()
print(t2 - t1)
# 6.57236599922

en comparación con

t1 = time()
for i in range(1000000):
    '{0:b}'.format(i)
t2 = time()
print(t2 - t1)
# 0.68017411232
Aziz Alto
fuente
eso devuelve '' para 0 sin embargo. ¿No sería la representación normal para 0 '0'?
dietbacon
si quieres ver ese 0 :), puedes reemplazarlo ''por '0', pero agregará un 0 inicial para cualquier número.
Aziz Alto
11

Resumen de alternativas:

n=42
assert  "-101010" == format(-n, 'b')
assert  "-101010" == "{0:b}".format(-n)
assert  "-101010" == (lambda x: x >= 0 and str(bin(x))[2:] or "-" + str(bin(x))[3:])(-n)
assert "0b101010" == bin(n)
assert   "101010" == bin(n)[2:]   # But this won't work for negative numbers.

Los colaboradores incluyen a John Fouhy , Tung Nguyen , mVChr , Martin Thoma . y Martijn Pieters.

BobStein-VisiBone
fuente
66
str.format()solo formatear un valor es exagerado. Ir directamente a la format()función: format(n, 'b'). No es necesario analizar el marcador de posición y compararlo con un argumento de esa manera.
Martijn Pieters
10

Como las respuestas anteriores utilizan principalmente el formato (), aquí hay una implementación de f-string.

integer = 7
bit_count = 5
print(f'{integer:0{bit_count}b}')

Salida:

00111

Para mayor comodidad, aquí está el enlace de documentos de Python para literales de cadena formateados: https://docs.python.org/3/reference/lexical_analysis.html#f-strings .

John Forbes
fuente
7
>>> format(123, 'b')
'1111011'
Sandu Ursu
fuente
5

Usando numpy pack / unpackbits, son tus mejores amigos.

Examples
--------
>>> a = np.array([[2], [7], [23]], dtype=np.uint8)
>>> a
array([[ 2],
       [ 7],
       [23]], dtype=uint8)
>>> b = np.unpackbits(a, axis=1)
>>> b
array([[0, 0, 0, 0, 0, 0, 1, 0],
       [0, 0, 0, 0, 0, 1, 1, 1],
       [0, 0, 0, 1, 0, 1, 1, 1]], dtype=uint8)
trampa
fuente
La pregunta es sobre una representación de cadena . Aún así, ¡resultó ser justo lo que estaba buscando sin pasar primero por la cadena! :)
Tom Hale
El doco dice: elementos desempaqueta de una uint8matriz en una matriz de salida binaria de valor. Muy bueno para valores de hasta 255.
Tom Hale
5

Para aquellos de nosotros que necesitamos convertir enteros con signo (rango -2 ** (dígitos-1) a 2 ** (dígitos-1) -1) a cadenas binarias complementarias de 2, esto funciona:

def int2bin(integer, digits):
if integer >= 0:
    return bin(integer)[2:].zfill(digits)
else:
    return bin(2**digits + integer)[2:]

Esto produce:

>>> int2bin(10, 8)
'00001010'
>>> int2bin(-10, 8)
'11110110'
>>> int2bin(-128, 8)
'10000000'
>>> int2bin(127, 8)
'01111111'
DeanM
fuente
4

A menos que no entienda lo que quiere decir con cadena binaria, creo que el módulo que está buscando es struct

Van Gale
fuente
4

Otra solución más con otro algoritmo, utilizando operadores bit a bit.

def int2bin(val):
    res=''
    while val>0:
        res += str(val&1)
        val=val>>1     # val=val/2 
    return res[::-1]   # reverse the string

Una versión más rápida sin invertir la cadena.

def int2bin(val):
   res=''
   while val>0:
       res = chr((val&1) + 0x30) + res
       val=val>>1    
   return res 
Reza Abtin
fuente
La segunda versión definitivamente no es más rápida, ya que terminas con algo así como un algoritmo O (N ^ 2) en lugar de un O (N). He visto cosas como esta que matan una aplicación (en cuanto al rendimiento) porque el desarrollador pensó que hacer un pase adicional al final era más lento que hacer algunas cosas adicionales en el primer bucle. Una vez arreglado, el tiempo de funcionamiento disminuyó de días a segundos.
Andreas Magnusson el
4
def binary(decimal) :
    otherBase = ""
    while decimal != 0 :
        otherBase  =  str(decimal % 2) + otherBase
        decimal    //=  2
    return otherBase

print binary(10)

salida:

1010

mukundan
fuente
4

puedes hacer así:

bin(10)[2:]

o:

f = str(bin(10))
c = []
c.append("".join(map(int, f[2:])))
print c
Skiller Dz
fuente
bin (n) .replace ("0b", "")
sanner little
3

Aquí está el código que acabo de implementar. ¡Este no es un método, pero puede usarlo como una función lista para usar !

def inttobinary(number):
  if number == 0:
    return str(0)
  result =""
  while (number != 0):
      remainder = number%2
      number = number/2
      result += str(remainder)
  return result[::-1] # to invert the string
quents
fuente
3

Aquí hay una solución simple usando la función divmod () que devuelve el recordatorio y el resultado de una división sin la fracción.

def dectobin(number):
    bin = ''
    while (number >= 1):
        number, rem = divmod(number, 2)
        bin = bin + str(rem)
    return bin
user210021
fuente
Necesita depuración. Las llamadas dectobin(10)resultaron en '0101'
Nate
3
n=input()
print(bin(n).replace("0b", ""))
dblaze
fuente
3

numpy.binary_repr(num, width=None)

Ejemplos del enlace de documentación anterior:

>>> np.binary_repr(3)
'11'
>>> np.binary_repr(-3)
'-11'
>>> np.binary_repr(3, width=4)
'0011'

El complemento de dos se devuelve cuando el número de entrada es negativo y se especifica el ancho:

>>> np.binary_repr(-3, width=3)
'101'
>>> np.binary_repr(-3, width=5)
'11101'
Tom Hale
fuente
2

Solución algo similar

def to_bin(dec):
    flag = True
    bin_str = ''
    while flag:
        remainder = dec % 2
        quotient = dec / 2
        if quotient == 0:
            flag = False
        bin_str += str(remainder)
        dec = quotient
    bin_str = bin_str[::-1] # reverse the string
    return bin_str 
Velero
fuente
2

Aquí hay otra forma de usar las matemáticas regulares, sin bucles, solo recursividad. (El caso trivial 0 no devuelve nada).

def toBin(num):
  if num == 0:
    return ""
  return toBin(num//2) + str(num%2)

print ([(toBin(i)) for i in range(10)])

['', '1', '10', '11', '100', '101', '110', '111', '1000', '1001']
ergonauta
fuente
2

Calculadora con todas las funciones necesarias para DEC, BIN, HEX: (hecho y probado con Python 3.5)

Puede cambiar los números de prueba de entrada y obtener los convertidos.

# CONVERTER: DEC / BIN / HEX

def dec2bin(d):
    # dec -> bin
    b = bin(d)
    return b

def dec2hex(d):
    # dec -> hex
    h = hex(d)
    return h

def bin2dec(b):
    # bin -> dec
    bin_numb="{0:b}".format(b)
    d = eval(bin_numb)
    return d,bin_numb

def bin2hex(b):
    # bin -> hex
    h = hex(b)
    return h

def hex2dec(h):
    # hex -> dec
    d = int(h)
    return d

def hex2bin(h):
    # hex -> bin
    b = bin(h)
    return b


## TESTING NUMBERS
numb_dec = 99
numb_bin = 0b0111 
numb_hex = 0xFF


## CALCULATIONS
res_dec2bin = dec2bin(numb_dec)
res_dec2hex = dec2hex(numb_dec)

res_bin2dec,bin_numb = bin2dec(numb_bin)
res_bin2hex = bin2hex(numb_bin)

res_hex2dec = hex2dec(numb_hex)
res_hex2bin = hex2bin(numb_hex)



## PRINTING
print('------- DECIMAL to BIN / HEX -------\n')
print('decimal:',numb_dec,'\nbin:    ',res_dec2bin,'\nhex:    ',res_dec2hex,'\n')

print('------- BINARY to DEC / HEX -------\n')
print('binary: ',bin_numb,'\ndec:    ',numb_bin,'\nhex:    ',res_bin2hex,'\n')

print('----- HEXADECIMAL to BIN / HEX -----\n')
print('hexadec:',hex(numb_hex),'\nbin:    ',res_hex2bin,'\ndec:    ',res_hex2dec,'\n')
HKC72
fuente
2

Para calcular el binario de números:

print("Binary is {0:>08b}".format(16))

Para calcular el decimal hexadecimal de un número :

print("Hexa Decimal is {0:>0x}".format(15))

Para calcular todos los no binarios hasta 16 ::

for i in range(17):
   print("{0:>2}: binary is {0:>08b}".format(i))

Para calcular Hexa decimal no hasta 17

 for i in range(17):
    print("{0:>2}: Hexa Decimal is {0:>0x}".format(i))
##as 2 digit is enogh for hexa decimal representation of a number
Rajesh Kumar Sahoo
fuente
1

Si estás dispuesto a renunciar a Python "puro" pero obtienes mucha potencia de fuego, está Sage , por ejemplo :

sage: a = 15
sage: a.binary()
'1111'

Notarás que regresa como una cadena, así que para usarlo como un número, querrás hacer algo como

sage: eval('0b'+b)
15
kcrisman
fuente
1
try:
    while True:
        p = ""
        a = input()
        while a != 0:
            l = a % 2
            b = a - l
            a = b / 2
            p = str(l) + p
        print(p)
except:
    print ("write 1 number")
usuario7930187
fuente
66
Es posible que desee agregar alguna explicación a lo que hizo allí.
Artless
1

Encontré un método que usa la operación de matriz para convertir decimal a binario.

import numpy as np
E_mat = np.tile(E,[1,M])
M_order = pow(2,(M-1-np.array(range(M)))).T
bindata = np.remainder(np.floor(E_mat /M_order).astype(np.int),2)

Ees entrada de datos decimales, Mes el orden binario. bindataes salida de datos binarios, que está en un formato de 1 por M matriz binaria.

Galle He
fuente
0

Aquí hay un simple convertidor binario a decimal que realiza bucles continuamente

t = 1
while t > 0:
    binaryNumber = input("Enter a binary No.")
    convertedNumber = int(binaryNumber, 2)

    print(convertedNumber)

print("")
Spencer Layland
fuente
Este es el orden inverso de lo que quiere el OP. Están buscando int a binario. Proporcionas binario a int.
Cecilia
0

Esta es mi respuesta, funciona bien ...!

def binary(value) :
    binary_value = ''
    while value !=1  :
        binary_value += str(value%2)
        value = value//2
    return '1'+binary_value[::-1]
Charunie Hansika AM
fuente
¿Qué pasa si pasa el valor 0? Por ejemplo binary(0), ¿obtendrás lo que esperas?
Andreas Magnusson