Python int para string binária?


530

Existem métodos Python enlatados para converter um número inteiro (ou longo) em uma string binária no Python?

Há uma infinidade de funções dec2bin () no Google ... Mas eu esperava poder usar uma função / biblioteca embutida.


Para uma abordagem oposta, para um algoritmo de processamento de string puro, consulte isso .
CopyPasteIt 15/03

Respostas:


750

O método de formato de string do Python pode ter uma especificação de formato.

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

Documentos de especificação de formato para Python 2

Documentos de especificação de formato para Python 3


86
str.format()apenas formatar um valor é um exagero. Vá direto para a format()função : format(n, 'b'). Não há necessidade de analisar o espaço reservado e associá-lo a um argumento; vá direto para a operação de formatação de valor. Use apenas str.format()se você precisar colocar o resultado formatado em uma string mais longa (por exemplo, use-a como modelo).
Martijn Pieters

29
@ Mike: Ou use a especificação de formatação. Adicione o número de dígitos com um inicial 0à sequência de formatação: format(10, '016b')formata para 16 dígitos com zeros iniciais.
Martijn Pieters

Nesse caso, o 0in "{0:b}"pode ser descartado não? Quero dizer, no caso em que apenas um número está sendo formatado, é correto colocar "{:b}", não é?
tomasyany

1
geralmente um usaria / representação bit 4/8 ...:"{:08b}".format(37)
Sparkler

2
f "{37: b}" no Python3.7 ou posterior.
DA

471

Se você procura bin()como equivalente ahex() , foi adicionado no python 2.6.

Exemplo:

>>> bin(10)
'0b1010'

66
Observe também que é mais rápido fazer str(bin(i))[2:](0,369s para 1000000ops) do que "{0:b}".format(i)(0,721s para 1000000ops)
mVChr

64
@mVChr Se alguém está convertendo números em uma representação binária ASCII, realmente espero que a velocidade não importe.
Nick T

29
@ MVChr: str.format()é a ferramenta errada de qualquer maneira, você usaria em seu format(i, 'b')lugar. Leve em consideração que isso também oferece opções de preenchimento e alinhamento; format(i, '016b')para formatar para um número binário de 16 bits preenchido com zero. Para fazer o mesmo, bin()você teria que adicionar uma str.zfill()chamada: bin(i)[2:].zfill(16)(não é necessário ligar str()!). format()A legibilidade e a flexibilidade (a formatação dinâmica é muito mais difícil bin()) são ótimas vantagens, não otimize o desempenho, a menos que você precise, até então otimizar a manutenção.
Martijn Pieters

O que significa [2:]?
Zero_cool 18/08/19

4
Obviamente, com o python 3.6+, agora você pode usar f"{37:b}".
Luke Davis

63

Python realmente faz alguma coisa já construído dentro para isso, a capacidade de fazer operações como '{0:b}'.format(42), o que lhe dará o padrão de bits (em uma string) para 42, ou 101010.


Para uma filosofia mais geral, nenhuma linguagem ou biblioteca dará à sua base de usuários tudo o que eles desejam. Se você estiver trabalhando em um ambiente que não forneça exatamente o que você precisa, colete trechos de código à medida que for desenvolvendo para garantir que você nunca precise escrever a mesma coisa duas vezes. Como, por exemplo, o pseudo-có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á sua sequência binária com base no valor decimal. Lembre-se de que é um pseudocódigo genérico que pode não ser o mais maneira eficiente de fazê-lo. Com as iterações que você parece estar propondo, não fará muita diferença. É realmente apenas uma orientação sobre como isso pode ser feito.

A idéia geral é usar o código de (em ordem de preferência):

  • o idioma ou bibliotecas internas.
  • bibliotecas de terceiros com licenças adequadas.
  • sua própria coleção.
  • algo novo que você precisa escrever (e salvar em sua própria coleção para mais tarde).

1
Alguns bons conselhos nesta resposta. Pena que o código é desnecessariamente lento. Você propõe um algo O (N ^ 2) onde um O (N) faria. A parte problemática está nas linhas s = "1" + se s = "0" + s. Cada um faz uma cópia desnecessária de s. Você deve reverter a string antes de devolvê-la.
Andreas Magnusson

@ Andréas, o que eu propus era usar '{0:b}'.format(42), o método lento era simplesmente um exemplo de como fazê-lo genericamente, que pode ou não ser O (n ^ 2), dependendo do idioma real usado. Parece apenas Python, já que o Python é uma linguagem de pseudo-código ideal, então vou mudar isso para deixar claro.
paxdiablo

Na verdade, seria uma linguagem bastante esotérica, onde s = "1" + snão estava O (N) quando sé um tipo de string. Talvez um idioma em que todas as strings sejam armazenadas para trás ou cada caractere seja um nó em uma lista vinculada? Para qualquer linguagem típica, uma string é basicamente uma matriz de caracteres. Nesse caso, o prefixo de uma string exige que uma cópia seja feita. De que outra forma você colocará o caractere antes dos outros caracteres?
Andreas Magnusson

Eu posso facilmente visualizar um tipo de string que consiste em um bloco de memória em que a string é justificada à direita dentro desse bloco e um deslocamento para seu caractere inicial. Para prefixar um caractere, basta reduzir o deslocamento e armazenar o caractere lá. Sim, isso seria esotérico, mas faz pouco sentido discutir sobre possíveis problemas do mundo real com um pouco de pseudo-código, especialmente porque você provavelmente não terá mais do que algumas dezenas de bits / iterações. Mesmo o tipo de bolha muito difamado é adequado se o tamanho dos dados for pequeno :-) De qualquer forma, adicionarei uma observação sobre eficiência.
paxdiablo 9/01

Claro, se a eficiência é importante, você provavelmente não escolheria python para começar. Ainda na minha experiência, ocorre com bastante frequência que o código que foi escrito de maneira ingênua usando algo O (N²) e testado com um pequeno conjunto de dados rapidamente se acostuma com um conjunto de dados muito maior porque "parece funcionar". De repente, você tem um código que leva horas para ser executado e, quando corrigido, pode levar apenas alguns segundos. Algos O (N²) são traiçoeiros porque parecem funcionar por um tempo, mas quando seus dados são dimensionados, eles não o fazem e, então, o cara que os escreveu parou de trabalhar e ninguém sabe por que as coisas demoram uma eternidade.
Andreas Magnusson

41

Se você deseja uma representação textual sem o prefixo 0b, pode usar o seguinte:

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

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

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

Quando você deseja uma representação de n bits:

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

Como alternativa, se você preferir ter uma função:

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)

5
Ou apenas use format(integer, 'b'). bin()é uma ferramenta de depuração, destinada especificamente à produção da sintaxe literal de número inteiro binário do Python , format()destinada a produzir formatos específicos.
Martijn Pieters

1
@MartijnPieters Muito obrigado por mencionar. Eu ajustei minha solução. Como você sabe que bin()é uma ferramenta de depuração destinada a produzir a sintaxe literal de número inteiro binário em Python? Não encontrei isso na documentação.
Martin Thoma

2
Da documentação: O resultado é uma expressão Python válida . Seu objetivo é produzir uma expressão Python, não produzir representações do usuário final. O mesmo se aplica a oct()e hex().
Martijn Pieters

4
Mais alternativas: se você deseja tornar a largura dinâmica, em vez de str.zfill()usar str.format()ou format()com um segundo argumento dinâmico: '{0:0{1}b}'.format(x, n)ou format(b, '0{}b'.format(n)).
Martijn Pieters

@MartijnPieters Uau, muito obrigado por esta entrada! Eu não sabia que isso era possível com o formato. No entanto, acho que minha resposta atual zfillé mais fácil de ler e entender do que o segundo argumento dinâmico, por isso vou manter isso.
Martin Thoma

38

Como referência:

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

Esta função pode converter um número inteiro positivo tão grande quanto 18446744073709551615, representado como sequência '1111111111111111111111111111111111111111111111111111111111111111'.

Ele pode ser modificado para exibir um número inteiro muito maior, embora possa não ser tão útil quanto "{0:b}".format()ou bin().


@GarethDavidson qual versão é essa? A declaração explícita pode ser de maior utilidade futura ao pesquisar no Google.
Lobo

Foi a versão 2.7, eu acho. Eu duvido que ele iria trabalhar em 3.x
Gareth Davidson

17

Uma maneira simples de fazer isso é usar o formato de string, consulte esta página .

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

E se você quiser ter um comprimento fixo da cadeia binária, poderá usar o seguinte:

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

Se o complemento de dois for necessário, a seguinte linha poderá ser usada:

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

onde n é a largura da cadeia binária.


16

Isto é para python 3 e mantém os zeros à esquerda!

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

insira a descrição da imagem aqui


1
Agradeço a resposta simples.
reergymerej

14

uma linha com lambda :

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

teste:

>>> binary(5)
'101'



EDIT :

mas então :(

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

em comparação com

t1 = time()
for i in range(1000000):
    '{0:b}'.format(i)
t2 = time()
print(t2 - t1)
# 0.68017411232

que retorna '' para 0, no entanto. A representação normal de 0 não seria '0'?
precisa saber é

se você quiser ver que 0 :), poderá substituir ''por '0', mas ele adicionará um 0 inicial para qualquer número.
Aziz Alto

11

Resumo das 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.

Os colaboradores incluem John Fouhy , Tung Nguyen , mVChr , Martin Thoma . e Martijn Pieters.


6
str.format()apenas formatar um valor é um exagero. Vá direto para a format()função: format(n, 'b'). Não é necessário analisar o espaço reservado e associá-lo a um argumento dessa maneira.
Martijn Pieters



5

Usando numpy pack / unpackbits, eles são seus melhores 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)

A questão é sobre uma representação de string . Ainda assim, isso era exatamente o que eu estava procurando sem passar pela string primeiro! :)
Tom Hale

O documento diz: Descompacta os elementos de uma uint8matriz em uma matriz de saída com valor binário. Tão bom para valores até 255.
Tom Hale

5

Para aqueles de nós que precisam converter números inteiros assinados (intervalo -2 ** (dígitos-1) para 2 ** (dígitos-1) -1) nas seqüências binárias de complemento de 2, isso funciona:

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

Isso produz:

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


4

Mais uma solução com outro algoritmo, usando 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

Uma versão mais rápida sem reverter a string.

def int2bin(val):
   res=''
   while val>0:
       res = chr((val&1) + 0x30) + res
       val=val>>1    
   return res 

A segunda versão definitivamente não é mais rápida, pois você acaba com um algoritmo O (N ^ 2) em vez de um O (N). Já vi coisas como essa matar um aplicativo (em termos de desempenho) porque o desenvolvedor pensou que fazer uma passagem extra no final era mais lento do que fazer algumas coisas extras no primeiro ciclo. Uma vez consertado, reduzia o tempo de execução de dias para segundos.
Andreas Magnusson

4
def binary(decimal) :
    otherBase = ""
    while decimal != 0 :
        otherBase  =  str(decimal % 2) + otherBase
        decimal    //=  2
    return otherBase

print binary(10)

resultado:

1010


4

você pode fazer assim:

bin(10)[2:]

ou:

f = str(bin(10))
c = []
c.append("".join(map(int, f[2:])))
print c

bin (n) .replace ("0b", "")
sanner little

3

Aqui está o código que acabei de implementar. Este não é um método, mas você pode usá-lo como uma função pronta para uso !

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

3

aqui está uma solução simples usando a função divmod () que retorna o lembrete e o resultado de uma divisão sem a fração.

def dectobin(number):
    bin = ''
    while (number >= 1):
        number, rem = divmod(number, 2)
        bin = bin + str(rem)
    return bin

Precisa de depuração. A chamada dectobin(10)resultou em '0101'
Nate


3

numpy.binary_repr(num, width=None)

Exemplos do link da documentação acima:

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

O complemento dos dois é retornado quando o número de entrada é negativo e a largura é especificada:

>>> np.binary_repr(-3, width=3)
'101'
>>> np.binary_repr(-3, width=5)
'11101'

2

Solução um pouco semelhante

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 

2

Aqui está outra maneira de usar a matemática regular, sem loops, apenas recursão. (O caso trivial 0 não retorna 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']

2

Calculadora com todas as funções necessárias para DEC, BIN, HEX: (fabricado e testado com Python 3.5)

Você pode alterar os números dos testes de entrada e obter os números 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')

2

Para calcular o binário de números:

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

Para calcular o decimal hexa de um número :

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

Para calcular todo o número binário até 16 ::

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

Para calcular o número decimal hexa até 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

1

Se você está disposto a desistir de Python "puro", mas ganhar muito poder de fogo, há o Sage - exemplo aqui :

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

Você notará que ele retorna como uma string; portanto, para usá-lo como um número, você gostaria de fazer algo como

sage: eval('0b'+b)
15

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

6
Talvez queira adicionar alguma explicação ao que você fez lá.
Artless

1

Eu encontrei um método usando a operação de matriz para converter decimal em binário.

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)

Eé entrada de dados decimais, Msão as ordens binárias. bindatasão dados binários de saída, que estão no formato 1 por M da matriz binária.


0

Aqui está um conversor binário para decimal simples que faz um loop contínuo

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

    print(convertedNumber)

print("")

Essa é a ordem inversa do que o OP deseja. Eles estão procurando int para binário. Você fornece binário para int.
Cecilia

0

Esta é a minha resposta, funciona bem ..!

def binary(value) :
    binary_value = ''
    while value !=1  :
        binary_value += str(value%2)
        value = value//2
    return '1'+binary_value[::-1]

E se você passar o valor 0? Por exemplo binary(0), você conseguirá o que espera?
Andreas Magnusson
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.