Перетворити на двійкові та зберегти провідні нулі в Python


154

Я намагаюся перетворити ціле число в бінарне за допомогою функції bin () в Python. Однак він завжди видаляє провідні нулі, які мені фактично потрібні, так що результат завжди є 8-бітовим:

Приклад:

bin(1) -> 0b1

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

Чи є спосіб зробити це?


Дивіться також: Python int to binary? , особливо моя відповідь з n-бітним поданням. Не зовсім те саме, але я прийшов до цього питання, шукаючи свою відповідь ...
Мартін Тома

Відповіді:


220

Використовуйте format()функцію :

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

format()Функція просто форматує вводити наступне за специфікацією формату міні - мови . Формат #робить формат, включає 0bпрефікс, а 010розмір форматує вихід, щоб він змістився в ширину 10 символів, з 0прокладкою; 2 символи для 0bпрефікса, інші 8 для двійкових цифр.

Це найбільш компактний і прямий варіант.

Якщо ви розміщуєте результат у більшому рядку, використовуйте відформатований рядковий літерал (3.6+) або використовуйте str.format()та поставте другий аргумент format()функції після двокрапки заповнювача {:..}:

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

Як це буває, навіть для простого форматування одного значення (так, не ставлячи результат у більший рядок), використання відформатованого літерального рядка швидше, ніж використання 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

Але я би використовував це лише в тому випадку, якщо продуктивність у тісному циклі має значення, оскільки format(...)краще передає наміри.

Якщо ви не хотіли 0bпрефікса, просто опустіть #і відрегулюйте довжину поля:

>>> format(14, '08b')
'00001110'

3
Саме те, що я шукав, таке форматування мені дуже допомагає. Я почав вивчати маніпуляції з бітами, і я гуглю за форматним бітом для чисел у Python. Знайшов це. Дякую.
kratostoical

Добре працює. Можна отримати трохи об'ємний, хоча. format(192,'08b')+'.'+format(0,'08b')+'.'+format(2,'08b')+'.'+format(33,'08b') 11000000.00000000.00000010.00100001
голоси

@ tjt263: Ось чому я прямо заявляю, що якщо виstr.format(){:..}
Martijn Pieters

1
@ tjt263: наприклад, використання f"{192:08b}.{0:08b}.{2:08b}.{33:08b}".
Martijn Pieters

Дуже хороша. Я ніколи б не знав, що це ви мали на увазі лише з пояснення. Але тепер я бачив ваш приклад, я, мабуть, ніколи його не забуду. Ура.
голоси

115
>>> '{:08b}'.format(1)
'00000001'

Див.: Міні-мова специфікації формату


Примітка для Python 2.6 або пізнішої версії, ви не можете опустити ідентифікатор позиційного аргументу раніше :, тому використовуйте

>>> '{0:08b}'.format(1)
'00000001'      

3
Тут не потрібно використовувати str.format()тут, коли format()це робитиме. Ви не вистачаєте 0bпрефікса.
Martijn Pieters

2
@MartijnPieters, str.formatє більш гнучким, ніж format()тому, що дозволить вам робити кілька змінних одночасно. Я постійно забуваю, що formatфункція навіть існує. Справді, в цьому випадку це цілком адекватно.
Марк Рансом

1
@MarkRansom: Саме тоді, коли ви використовуєте str.format()лише один {}елемент, жоден інший текст, ви не використовуєте шаблони рядків, ви форматуєте одне значення . У такому випадку просто використовуйте format(). :-)
Martijn Pieters


9

Можна використовувати міні-мову форматування рядків:

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

Демонстрація:

print binary(1)

Вихід:

'0b00000001'

EDIT: заснований на ідеї @Martijn Pieters

def binary(num, length=8):
    return format(num, '#0{}b'.format(length + 2))

2
Цю ж мову форматування можна використовувати для включення префікса для вас. Використовуйте #. Є також format(), що дозволяє вам заощаджувати шаблони з повним рядком.
Martijn Pieters

2

Під час використання Python >= 3.6найчистішим способом є використання f-рядків із форматуванням рядків :

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

Пояснення:

  • var змінна для форматування
  • : все після цього - специфікатор формату
  • #використовувати альтернативну форму (додає 0bпрефікс)
  • 0 колодка з нулями
  • 10килимок на загальну довжину від 10 (сюди входять 2 знаки для 0b)
  • b використовувати двійкове представлення для числа

Ні, це не найчистіше, якщо тільки ви не зробите більше з рядком, ніж просто один заповнювач . В іншому випадку format(var, "#010b")повідомляється про наміри набагато краще. Це, однак, найшвидший варіант. Але ви це вже знаєте, правда, тому що я вже висвітлюю все, що ви написали у своїй відповіді.
Martijn Pieters

1

Іноді потрібно просто простий вкладиш:

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

Пітон 3


1
Зауважте, що це [ ]не повинно бути потрібним - join()приймає вираз генератора. ''.join('{0:08b}'.format(ord(x)) for x in input)
Крістоф Буршка

@ChristophBurschka зауважимо, що оскільки str.join()потрібно зробити два проходи, вхід генератора спочатку переходить до списку перед тим, як приєднатися. Це потребує певних витрат на продуктивність, і тут краще насправді передати розуміння списку, а не генераторний вираз. Це одне, якщо вони винятки з правила.
Martijn Pieters

-1

Можна використовувати щось подібне

("{:0%db}"%length).format(num)

2
Будь-ласка, використовуйте код коду для свого фрагмента коду. І якщо ви дійсно хочете, щоб це була хороша відповідь, тоді також додайте кілька коментарів щодо того, чому це рішення вирішує питання ОП.
β.εηοιτ.βε

Вам не потрібно використовувати інший стиль форматування рядків лише для додавання змінної ширини. Просто додайте ще одного заповнювача:"{:0{l}b}".format(num, l=length)
Martijn Pieters

-1

ви можете використовувати rjust string метод синтаксису python: string.rjust (довжина, fillchar) fillchar необов'язковий

і для вашого питання ви прищі пишіть так

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

тож буде "0b00000001"


Виникає синтаксична помилка. Але що ще важливіше, він взагалі не відповідає на питання, що стосується перетворення intтексту на його текстове бінарне подання; ви навіть не починаєте з int.
Тьєррі Латуй

-3

Ви можете використовувати zfill:

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

відбитки:

01
10
100

Мені подобається це рішення, оскільки воно допомагає не тільки при виведенні числа, але і тоді, коли вам потрібно призначити його змінної ... наприклад - x = str (datetime.date.today (). Month) .zfill (2) повернути х як "02" за місяць феб.


1
Проблема з zfill полягає в тому, що вона розглядає двійковий рядок як рядок і додає нулі перед двійковим індикатором 'b' ... наприклад, bin(14) дає `` 0b1110 '' і bin(14).zfill(8) дає `'000b1110' 'не` `0b00001110' ', що саме бажано
Шон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.