Перетворити на двійкові та зберегти провідні нулі в 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.