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?


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'

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'      

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


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

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

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


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)

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”


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.


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,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.