Python int na ciąg binarny?

529

Czy są jakieś standardowe metody Pythona do konwersji liczby całkowitej (lub długiej) na ciąg binarny w Pythonie?

Istnieje mnóstwo funkcji dec2bin () w Google ... Ale miałem nadzieję, że będę mógł użyć wbudowanej funkcji / biblioteki.

Nate
źródło
Odwrotne podejście, dla algorytmu przetwarzania czystego łańcucha, zobacz to .
CopyPasteIt

Odpowiedzi:

750

Metoda formatu ciągu znaków w Pythonie może przyjmować specyfikację formatu.

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

Sformatuj dokumentację specyfikacji dla Python 2

Sformatuj dokumentację specyfikacji dla Python 3

Tung Nguyen
źródło
86
str.format()tylko sformatowanie jednej wartości to przesada. Idź prosto do format()funkcji : format(n, 'b'). Nie ma potrzeby analizowania symbolu zastępczego i dopasowania go do argumentu, przejdź od razu do samej operacji formatowania wartości. Używaj tylko str.format()wtedy, gdy musisz umieścić sformatowany wynik w dłuższym ciągu (np. Użyj go jako szablonu).
Martijn Pieters
29
@mike: Lub użyj specyfikacji formatowania. Dodaj liczbę cyfr prowadzących 0do ciągu formatującego: format(10, '016b')formatuje do 16 cyfr z wiodącymi zerami.
Martijn Pieters
W tym przypadku 0na "{0:b}"nie można spadła? To znaczy, w przypadku, gdy formatowana jest tylko jedna liczba, poprawne jest umieszczenie "{:b}", prawda?
tomasyany
1
zwykle używa się reprezentacji 4/8 / ... bitów:"{:08b}".format(37)
Sparkler
2
f „{37: b}” w Python3.7 lub nowszym.
DA
471

Jeśli szukasz bin()jako odpowiednika hex(), został dodany w Pythonie 2.6.

Przykład:

>>> bin(10)
'0b1010'
John Fouhy
źródło
66
Zauważ też, że jest to szybsze str(bin(i))[2:](0,369s dla 1000000opsów) niż "{0:b}".format(i)(0,721s dla 1000000opsów)
mVChr 30.10.13
64
@mVChr, jeśli ktoś konwertuje liczby na reprezentację binarną ASCII, naprawdę mam nadzieję, że prędkość nie ma znaczenia.
Nick T
29
@mVChr: ​​i tak str.format()jest niewłaściwym narzędziem, którego byś użył format(i, 'b'). Weź jednak pod uwagę, że daje to również opcje dopełniania i wyrównania; format(i, '016b')sformatować do 16-bitowej liczby binarnej z wypełnieniem zerowym. Aby to samo bin()zrobić, musisz dodać str.zfill()połączenie: bin(i)[2:].zfill(16)(nie musisz dzwonić str()!). format()Czytelność i elastyczność (dynamiczne formatowanie jest znacznie trudniejsze bin()) to świetne kompromisy, nie optymalizuj pod kątem wydajności, chyba że musisz, do tego czasu zoptymalizuj pod kątem łatwości konserwacji.
Martijn Pieters
Co oznacza [2:]?
zero_cool
4
Oczywiście w Pythonie 3.6+ możesz teraz używać f"{37:b}".
Luke Davis
63

Python rzeczywiście robi coś już zbudowany w do tego, zdolność do czynności takich jak '{0:b}'.format(42), co daje wzór bitowy (w sznurku) do 42lub 101010.


W przypadku bardziej ogólnej filozofii żaden język ani biblioteka nie da swojej bazie użytkowników wszystkiego , czego pragną. Jeśli pracujesz w środowisku, które nie zapewnia dokładnie tego, czego potrzebujesz, powinieneś zbierać fragmenty kodu w miarę rozwoju, aby mieć pewność, że nigdy nie będziesz musiał pisać tego samego dwa razy. Takich jak na przykład pseudo-kod:

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

który zbuduje ciąg binarny na podstawie wartości dziesiętnej. Wystarczy pamiętać, że to generic trochę pseudo-kodu, który może nie być najbardziej skuteczny sposób to zrobić chociaż, z iteracji wydają się być zaproponowanie, nie będzie dużej różnicy. To naprawdę jest tylko wskazówką, jak można to zrobić.

Ogólna idea polega na użyciu kodu z (w kolejności preferencji):

  • język lub wbudowane biblioteki.
  • biblioteki stron trzecich z odpowiednimi licencjami.
  • twoja własna kolekcja.
  • coś nowego, co musisz napisać (i zapisać we własnej kolekcji na później).
paxdiablo
źródło
1
Kilka dobrych rad w tej odpowiedzi. Szkoda tylko, że kod jest niepotrzebnie wolny. Proponujesz algo O (N ^ 2) tam, gdzie zrobiłby to O (N). Problematyczna część znajduje się w wierszach s = "1" + si s = "0" + s. Każda z nich tworzy niepotrzebną kopię s. Zamiast tego powinieneś odwrócić ciąg bezpośrednio przed jego zwróceniem.
Andreas Magnusson
@Andreas, to, co zaproponowałem, to użycie '{0:b}'.format(42), metoda powolna była po prostu przykładem tego, jak to zrobić ogólnie, którym może być O (n ^ 2) w zależności od używanego języka. Wygląda tylko jak Python, ponieważ Python jest idealnym językiem pseudokodu, więc zmienię to, aby było jasne.
paxdiablo
Właściwie byłby to dość ezoteryczny język, w którym s = "1" + snie było O (N), gdy sjest typem łańcucha. Może język, w którym wszystkie ciągi są przechowywane wstecz lub każdy znak jest węzłem na liście połączonej? Dla każdego typowego języka ciąg znaków jest w zasadzie tablicą znaków. W takim przypadku prefiks ciągu wymaga wykonania kopii, w jaki sposób zamierzasz umieścić znak przed innymi znakami?
Andreas Magnusson
Mogę łatwo wyobrazić sobie typ łańcucha, który składa się z bloku pamięci, w którym łańcuch jest odpowiednio wyjustowany w tym bloku, oraz przesunięcie względem jego początkowego znaku. Aby poprzedzić znak, należy po prostu zmniejszyć przesunięcie i zapisać tam znak. Tak, byłoby to ezoteryczne, ale nie ma dla mnie sensu spieranie się o możliwe problemy w świecie rzeczywistym z odrobiną pseudo-kodu, zwłaszcza, że prawdopodobnie nie będziesz mieć więcej niż kilkudziesięciu bitów / iteracji. Nawet bardzo zły typ bąbelków jest odpowiedni, jeśli twój rozmiar danych jest mały :-) W każdym razie dodam notatkę o wydajności.
paxdiablo
Jasne, jeśli wydajność jest ważna, prawdopodobnie nie wybrałbyś Pythona na początek. Jednak z mojego doświadczenia wynika, że ​​dość często kod, który został naiwnie napisany za pomocą algo O (N²) i przetestowany z małym zestawem danych, szybko przyzwyczaja się do znacznie większego zestawu danych, ponieważ „wydaje się, że działa”. Nagle masz kod, którego uruchomienie zajmuje wiele godzin, a gdy jest naprawiony, może zająć tylko kilka sekund. Algony O (N²) są podstępne, ponieważ wydają się działać przez jakiś czas, ale kiedy twoje dane się skalują, nie robią tego, a do tego czasu facet, który je napisał, zrezygnował i nikt nie wie, dlaczego wszystko trwa wiecznie.
Andreas Magnusson
41

Jeśli chcesz reprezentację tekstową bez prefiksu 0b, możesz użyć tego:

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

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

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

Kiedy chcesz reprezentacji n-bitowej:

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

Alternatywnie, jeśli wolisz mieć funkcję:

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
źródło
5
Lub po prostu użyj format(integer, 'b'). bin()jest narzędziem do debugowania, specjalnie ukierunkowanym na tworzenie binarnej składni całkowitej literału Pythona , format()przeznaczonym do tworzenia określonych formatów.
Martijn Pieters
1
@MartijnPieters Bardzo dziękuję za wzmiankę o tym. Dostosowałem swoje rozwiązanie. Skąd wiesz, że bin()jest to narzędzie do debugowania, którego celem jest tworzenie binarnej składni całkowitej literału Pythona? Nie mogłem tego znaleźć w dokumentacji.
Martin Thoma,
2
Z dokumentacji: Wynikiem jest prawidłowe wyrażenie w języku Python . Jego celem jest stworzenie wyrażenia w języku Python, a nie reprezentacje użytkowników końcowych. To samo dotyczy oct()i hex().
Martijn Pieters
4
Więcej alternatyw: jeśli zamierzasz uczynić szerokość dynamiczną, zamiast str.zfill()możesz użyć str.format()lub format()z dynamicznym drugim argumentem: '{0:0{1}b}'.format(x, n)lub format(b, '0{}b'.format(n)).
Martijn Pieters
@MartijnPieters Wow, bardzo dziękuję za ten wkład! Nie wiedziałem, że było to możliwe dzięki formatowi. Myślę jednak, że moja obecna odpowiedź zfilljest łatwiejsza do odczytania i zrozumienia niż dynamiczny drugi argument, więc zachowam to.
Martin Thoma,
37

Jako odniesienie:

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

Ta funkcja może konwertować dodatnią liczbę całkowitą tak dużą, jak 18446744073709551615, reprezentowaną przez ciąg '1111111111111111111111111111111111111111111111111111111111111111'.

Można go zmodyfikować, aby obsługiwał znacznie większą liczbę całkowitą, chociaż może nie być tak przydatny jak "{0:b}".format()lub bin().

kctong529
źródło
@GarethDavidson, która to wersja? Wyraźne stwierdzenie tego może być bardziej przydatne w przyszłości podczas przeglądania go.
Wolf
To chyba wersja 2.7. Wątpię, czy zadziałałoby w wersji 3.x
Gareth Davidson
17

Prostym sposobem na to jest użycie formatu ciągu, zobacz tę stronę .

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

A jeśli chcesz mieć stałą długość ciągu binarnego, możesz użyć tego:

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

Jeśli wymagane jest uzupełnienie dwóch, można użyć następującego wiersza:

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

gdzie n jest szerokością ciągu binarnego.

Xiang
źródło
16

To dotyczy Pythona 3 i zachowuje wiodące zera!

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

wprowadź opis zdjęcia tutaj

grepit
źródło
1
Doceniam prostą odpowiedź.
reergymerej
14

jednowarstwowy z lambda :

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

test:

>>> binary(5)
'101'



EDYCJA :

ale wtedy :(

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

w porównaniu do

t1 = time()
for i in range(1000000):
    '{0:b}'.format(i)
t2 = time()
print(t2 - t1)
# 0.68017411232
Aziz Alto
źródło
która zwraca „” dla 0. Czy normalna reprezentacja dla 0 nie byłaby „0”?
dietbacon
jeśli chce zobaczyć, że 0 :), można zastąpić ''z '0', ale doda cyfrę 0 dla dowolnej liczby.
Aziz Alto
11

Podsumowanie alternatyw:

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.

Współautorzy to John Fouhy , Tung Nguyen , mVChr , Martin Thoma . i Martijn Pieters.

BobStein-VisiBone
źródło
6
str.format()tylko sformatowanie jednej wartości to przesada. Idź prosto do format()funkcji: format(n, 'b'). Nie trzeba analizować symbolu zastępczego i dopasowywać go do argumentu w ten sposób.
Martijn Pieters
10

Ponieważ w poprzednich odpowiedziach najczęściej używany był format (), oto implementacja ciągu f-string.

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

Wynik:

00111

Dla wygody tutaj jest link do docs docs sformatowanych literałów łańcuchowych: https://docs.python.org/3/reference/lexical_analysis.html#f-strings .

John Forbes
źródło
7
>>> format(123, 'b')
'1111011'
Sandu Ursu
źródło
5

Używając numpy pack / unpackbits, są twoimi najlepszymi przyjaciółmi.

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)
pułapka
źródło
Pytanie dotyczy reprezentacji ciągu . Mimo to stało się to tym, czego szukałem, nie przechodząc najpierw przez sznurek! :)
Tom Hale
Doco mówi: rozpakowuje elementy uint8tablicy do tablicy wyjścia binarnego wycenione. Tak dobre dla wartości do 255.
Tom Hale
5

Dla tych z nas, którzy muszą konwertować podpisane liczby całkowite (zakres -2 ** (cyfry-1) na 2 ** (cyfry-1) -1) na ciągi binarne dopełniające 2, działa to:

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

Daje to:

>>> int2bin(10, 8)
'00001010'
>>> int2bin(-10, 8)
'11110110'
>>> int2bin(-128, 8)
'10000000'
>>> int2bin(127, 8)
'01111111'
DeanM
źródło
4

Chyba, że ​​nie rozumiem, co masz na myśli przez ciąg binarny, myślę, że moduł, którego szukasz, to struct

Van Gale
źródło
4

Jeszcze inne rozwiązanie z innym algorytmem, wykorzystujące operatory bitowe.

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

Szybsza wersja bez odwracania łańcucha.

def int2bin(val):
   res=''
   while val>0:
       res = chr((val&1) + 0x30) + res
       val=val>>1    
   return res 
Reza Abtin
źródło
Druga wersja zdecydowanie nie jest szybsza, ponieważ zamiast O (N) powstaje coś w rodzaju algorytmu O (N ^ 2). Widziałem takie rzeczy, jak zabijanie aplikacji (pod względem wydajności), ponieważ deweloper pomyślał, że wykonanie dodatkowego przejścia na końcu było wolniejsze niż wykonanie dodatkowych czynności w pierwszej pętli. Raz naprawiony skrócił czas pracy z dni do sekund.
Andreas Magnusson,
4
def binary(decimal) :
    otherBase = ""
    while decimal != 0 :
        otherBase  =  str(decimal % 2) + otherBase
        decimal    //=  2
    return otherBase

print binary(10)

wynik:

1010

Mukundan
źródło
4

możesz to zrobić:

bin(10)[2:]

lub:

f = str(bin(10))
c = []
c.append("".join(map(int, f[2:])))
print c
Skiller Dz
źródło
bin (n) .replace („0b”, „”)
zdrowszy mały
3

Oto kod, który właśnie zaimplementowałem. To nie jest metoda, ale możesz jej użyć jako funkcji gotowej do użycia !

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
źródło
3

oto proste rozwiązanie wykorzystujące funkcję divmod (), która zwraca przypomnienie i wynik podziału bez ułamka.

def dectobin(number):
    bin = ''
    while (number >= 1):
        number, rem = divmod(number, 2)
        bin = bin + str(rem)
    return bin
użytkownik210021
źródło
Potrzebuje debugowania. Wywołanie dectobin(10)spowodowało „0101”
Nate
3
n=input()
print(bin(n).replace("0b", ""))
dblaze
źródło
3

numpy.binary_repr(num, width=None)

Przykłady z linku do dokumentacji powyżej:

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

Uzupełnienie dwóch jest zwracane, gdy liczba wejściowa jest ujemna, a szerokość jest określona:

>>> np.binary_repr(-3, width=3)
'101'
>>> np.binary_repr(-3, width=5)
'11101'
Tom Hale
źródło
2

Nieco podobne rozwiązanie

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 
Kupiec
źródło
2

Oto jeszcze jeden sposób, używając zwykłej matematyki, bez pętli, tylko rekurencja. (Trywialny przypadek 0 nic nie zwraca).

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']
ergonaut
źródło
2

Kalkulator ze wszystkimi niezbędnymi funkcjami dla DEC, BIN, HEX: (stworzony i przetestowany w Pythonie 3.5)

Możesz zmienić wejściowe numery testowe i uzyskać przekonwertowane.

# 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
źródło
2

Aby obliczyć liczbę binarną liczb:

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

Aby obliczyć liczbę dziesiętną szesnastkową liczby :

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

Aby obliczyć wszystkie dane binarne nie do 16:

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

Aby obliczyć liczbę dziesiętną szesnastkową nie do 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
źródło
1

Jeśli chcesz zrezygnować z „czystego” Pythona, ale zyskać dużą siłę ognia, jest Sage - przykład tutaj :

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

Zauważysz, że zwraca jako ciąg, więc aby użyć go jako liczby, którą chcesz zrobić

sage: eval('0b'+b)
15
kcrisman
źródło
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")
użytkownik7930187
źródło
6
Może chcesz dodać wyjaśnienie do tego, co tam zrobiłeś.
Artless
1

Znalazłem metodę używającą operacji macierzowej do konwersji dziesiętnej na binarną.

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)

Eto wejściowe dane dziesiętne, Mto porządki binarne. bindatato wyjściowe dane binarne, które mają format 1 na M macierzy binarnej.

Galle He
źródło
0

Oto prosty konwerter binarny na dziesiętny, który ciągle się zapętla

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

    print(convertedNumber)

print("")
Spencer Layland
źródło
Jest to odwrotna kolejność niż chce OP. Szukają int do binarnego. Podajesz binarny do int.
Cecilia,
0

To jest moja odpowiedź, działa dobrze ..!

def binary(value) :
    binary_value = ''
    while value !=1  :
        binary_value += str(value%2)
        value = value//2
    return '1'+binary_value[::-1]
Charunie Hansika AM
źródło
Co jeśli przekażesz wartość 0? Np. binary(0)Czy dostaniesz to, czego oczekujesz?
Andreas Magnusson