Konwertuj na binarny i zachowaj wiodące zera w Pythonie

154

Próbuję przekonwertować liczbę całkowitą na binarną za pomocą funkcji bin () w Pythonie. Jednak zawsze usuwa wiodące zera, których faktycznie potrzebuję, tak że wynik jest zawsze 8-bitowy:

Przykład:

bin(1) -> 0b1

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

Czy jest na to sposób?

Niels Sønderbæk
źródło
Zobacz też: Python int to binary? , zwłaszcza moja odpowiedź z reprezentacją n-bitową. Nie do końca to samo, ale doszedłem do tego pytania, szukając odpowiedzi ...
Martin Thoma

Odpowiedzi:

220

Użyj format()funkcji :

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

format()Funkcja po prostu formatuje wejście w następstwie specyfikacji formatu mini języku . #Sprawia format zawierać 0bprefiks, a 010wielkość formatuje wyjście wpasować szerokość 10 znaków, z 0wyściółką; 2 znaki na 0bprefiks, pozostałe 8 na cyfry binarne.

Jest to najbardziej kompaktowa i bezpośrednia opcja.

Jeśli umieszczasz wynik w większym ciągu, użyj sformatowanego literału ciągu (3.6+) lub użyj str.format()i umieść drugi argument format()funkcji po dwukropku symbolu zastępczego {:..}:

>>> 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'

Tak się składa, że ​​nawet przy formatowaniu pojedynczej wartości (bez umieszczania wyniku w większym ciągu) użycie sformatowanego literału ciągu jest szybsze niż użycie 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

Ale użyłbym tego tylko wtedy, gdy liczy się wydajność w ciasnej pętli, ponieważ format(...)lepiej przekazuje intencję.

Jeśli nie chcesz 0bprefiksu, po prostu upuść #i dostosuj długość pola:

>>> format(14, '08b')
'00001110'
Martijn Pieters
źródło
3
Dokładnie to, czego szukałem, to formatowanie jest dla mnie bardzo pomocne. Zacząłem uczyć się manipulacji bitami i szukałem w Google formatowania bitów dla liczb w Pythonie. Znajdź to. Dziękuję Ci.
kratostoical
Działa ładnie. Może być jednak trochę nieporęczny. format(192,'08b')+'.'+format(0,'08b')+'.'+format(2,'08b')+'.'+format(33,'08b') 11000000.00000000.00000010.00100001
głosy
@ tjt263: Dlatego wyraźnie stwierdzam, że jeśli umieszczasz wynik w większym ciągu, użyj sformatowanego literału ciągu (3.6+) lub użyj str.format()i umieść drugi argument funkcji format () po dwukropku symbolu zastępczego {:..}:
Martijn Pieters
1
@ tjt263: np f"{192:08b}.{0:08b}.{2:08b}.{33:08b}". użyj .
Martijn Pieters
Bardzo dobrze. Nigdy bym się nie domyślił, że to właśnie masz na myśli z samego wyjaśnienia. Ale teraz widziałem twój przykład, prawdopodobnie nigdy go nie zapomnę. Twoje zdrowie.
głosy
115
>>> '{:08b}'.format(1)
'00000001'

Zobacz: Specyfikacja formatu Mini-język


Uwaga dla Pythona 2.6 lub starszego, nie możesz wcześniej pominąć identyfikatora argumentu pozycyjnego :, więc użyj

>>> '{0:08b}'.format(1)
'00000001'      
bwbrowning
źródło
3
Nie ma potrzeby używania str.format()tutaj, kiedy format()zrobi. Brakuje 0bprzedrostka.
Martijn Pieters
2
@MartijnPieters str.formatjest bardziej elastyczny niż format()dlatego, że pozwala na jednoczesne wykonywanie wielu zmiennych. Ciągle zapominam, że ta formatfunkcja w ogóle istnieje. Trzeba przyznać, że w tym przypadku jest to całkowicie wystarczające.
Mark Ransom
1
@MarkRansom: Dokładnie, gdy używasz str.format()tylko jednego {}elementu, żadnego innego tekstu, nie używasz szablonów ciągów, formatujesz jedną wartość . W takim przypadku po prostu użyj format(). :-)
Martijn Pieters
30

ja używam

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

wydrukuje

'00000001'
rekinyz
źródło
9

Możesz użyć mini języka formatowania ciągów:

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

Próbny:

print binary(1)

Wynik:

'0b00000001'

EDYCJA: na podstawie pomysłu @Martijn Pieters

def binary(num, length=8):
    return format(num, '#0{}b'.format(length + 2))
Peter Varo
źródło
2
Ten sam język formatowania może być użyty do dołączenia prefiksu. Użyj #. Jest też format(), co oszczędza ci konieczności tworzenia pełnego szablonu ciągu.
Martijn Pieters
2

Korzystając z Pythona >= 3.6, najczystszym sposobem jest użycie f-stringów z formatowaniem ciągów :

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

Wyjaśnienie:

  • var zmienna do sformatowania
  • : wszystko po tym jest specyfikatorem formatu
  • #użyj alternatywnej formy (dodaje 0bprzedrostek)
  • 0 wypełnij zerami
  • 10pad do całkowitej długości z 10 (w tym 2 znaki dla 0b)
  • b użyj reprezentacji binarnej dla liczby
ruohola
źródło
Nie, nie jest to najczystsze, chyba że zrobisz więcej z ciągiem niż tylko pojedynczy symbol zastępczy . W przeciwnym razie znacznie lepiej format(var, "#010b")przekazuje intencje . Jest to jednak najszybsza opcja. Ale już to wiesz, prawda, ponieważ już opisuję wszystko, co zamieściłeś w mojej odpowiedzi.
Martijn Pieters
1

Czasami potrzebujesz tylko jednego prostego wkładu:

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

Python 3

znak
źródło
1
Zauważ, że [ ]nie powinno być potrzebne - join()akceptuje wyrażenie generatora. ''.join('{0:08b}'.format(ord(x)) for x in input)
Christoph Burschka
@ChristophBurschka zauważ, że ze względu str.join()na konieczność wykonania dwóch przebiegów wejście generatora jest najpierw konwertowane na listę przed połączeniem. Ma to trochę negatywny wpływ na wydajność i czy w rzeczywistości lepiej jest tutaj przekazać zrozumienie listy niż wyrażenie generatora. To jeden, jeśli są wyjątkami od reguły.
Martijn Pieters
-1

Możesz użyć czegoś takiego

("{:0%db}"%length).format(num)
Adam
źródło
2
W swoim fragmencie kodu użyj przynajmniej bloku kodu. A jeśli naprawdę chcesz, aby była to dobra odpowiedź, dodaj też kilka komentarzy, dlaczego to rozwiązanie rozwiązuje pytanie OP.
β.εηοιτ.βε
Nie musisz używać innego stylu formatowania ciągu, aby dodać zmienną szerokość. Po prostu dodaj kolejny symbol zastępczy:"{:0{l}b}".format(num, l=length)
Martijn Pieters
-1

możesz użyć metody ciągów rjust składni Pythona: string.rjust (length, fillchar) fillchar jest opcjonalne

a na swoje pytanie piszesz w ten sposób

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

więc będzie to „0b00000001”

Jaydeep Mahajan
źródło
Wystąpił błąd składni. Ale co ważniejsze, w ogóle nie odpowiada na pytanie, które dotyczy konwersji an intdo jego tekstowej reprezentacji binarnej; nawet nie zaczynasz od int.
Thierry Lathuille
-3

Możesz użyć zfill:

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

wydruki:

01
10
100

Podoba mi się to rozwiązanie, ponieważ pomaga nie tylko przy wyprowadzaniu liczby, ale gdy trzeba przypisać ją do zmiennej ... np. - x = str (datetime.date.today (). Month) .zfill (2) będzie zwraca x jako „02” dla miesiąca lutego.

Anshul Garg
źródło
1
Problem z zfill polega na tym, że traktuje ciąg binarny jak ciąg i dodaje zera przed binarnym wskaźnikiem 'b' ... np. bin(14) daje `` 0b1110 '' i bin(14).zfill(8) daje `` 000b1110 '' `` nie '' 0b00001110 '', co jest tym, czego oczekujemy
Shaun,