Преобразовать в двоичный код и сохранить ведущие нули в Python

155

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

Пример:

bin(1) -> 0b1

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

Есть ли способ сделать это?

Нильс Сённербек
источник
Смотрите также: Python int в двоичный файл? особенно мой ответ с n-битным представлением. Не совсем то же самое, но я пришел к этому вопросу в поисках своего ответа ...
Мартин Тома

Ответы:

221

Используйте 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. Нашел это. Спасибо.
Кратостое
Работает хорошо. Может быть немного громоздким, хотя. format(192,'08b')+'.'+format(0,'08b')+'.'+format(2,'08b')+'.'+format(33,'08b') 11000000.00000000.00000010.00100001
голоса
@ tjt263: Вот почему я прямо заявляю, что если вы помещаете результат в строку большего размера, используйте форматированный строковый литерал (3.6+) или используйте str.format()второй аргумент для функции format () после двоеточия заполнителя {:..}:
Мартейн Питерс
1
@ tjt263: например, использовать f"{192:08b}.{0:08b}.{2:08b}.{33:08b}".
Мартин Питерс
Очень хорошо. Я никогда бы не узнал, что ты имел в виду только из объяснений. Но теперь я видел твой пример, я, наверное, никогда его не забуду. Приветствия.
голоса
115
>>> '{:08b}'.format(1)
'00000001'

См .: Спецификация формата Mini-Language


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

>>> '{0:08b}'.format(1)
'00000001'      
bwbrowning
источник
3
Нет необходимости использовать str.format()здесь, когда format()будет делать. Вам не хватает 0bпрефикса.
Мартин Питерс
2
@MartijnPieters, str.formatболее гибкий, чем format()потому, что он позволяет вам делать несколько переменных одновременно. Я постоянно забываю, что эта formatфункция даже существует. По общему признанию это совершенно адекватно в этом случае.
Марк Рэнсом
1
@MarkRansom: Точно, когда вы используете только str.format()с одним {}элементом, без другого текста, вы не используете строковые шаблоны, вы форматируете одно значение . В этом случае просто используйте format(). :-)
Мартин Питерс
30

Я использую

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

распечатает

'00000001'
rekinyz
источник
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'

РЕДАКТИРОВАТЬ: на основе идеи @Martijn Pieters

def binary(num, length=8):
    return format(num, '#0{}b'.format(length + 2))
Питер Варо
источник
2
Тот же язык форматирования может быть использован для включения префикса для вас. Использование #. Существует также format(), что избавляет вас от необходимости делать полный шаблон строки.
Мартин Питерс
2

При использовании Python >= 3.6самый простой способ - использовать f-строки с форматированием строк :

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

Объяснение:

  • var переменная для форматирования
  • : все после этого является спецификатором формата
  • #используйте альтернативную форму (добавляет 0bпрефикс)
  • 0 блокнот с нулями
  • 10колодки на общую длину от 10 (включая 2 символа для 0b)
  • b использовать двоичное представление для числа
Руохола
источник
Нет, он не самый чистый, если только вы не делаете больше со строкой, чем просто один заполнитель . В противном случае format(var, "#010b")общение намерение намного лучше. Это, однако, самый быстрый вариант. Но вы уже знаете это, верно, потому что я уже охватил все, что вы опубликовали в моем ответе.
Мартин Питерс
1

Иногда вам просто нужен простой вкладыш:

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

Python 3

отметка
источник
1
Обратите внимание, что [ ]не нужно - join()принимает выражение генератора. ''.join('{0:08b}'.format(ord(x)) for x in input)
Кристоф Буршка
@ChristophBurschka обратите внимание, что, поскольку str.join()необходимо выполнить два прохода, вход генератора сначала преобразуется в список перед присоединением. Это немного сказывается на производительности, и на самом деле здесь лучше передать понимание списка, а не выражение генератора. Это один, если их исключения из правил.
Мартин Питерс
-1

Вы можете использовать что-то вроде этого

("{:0%db}"%length).format(num)
Адам
источник
2
Пожалуйста, используйте хотя бы блок кода для своего фрагмента кода. И если вы действительно хотите, чтобы это был хороший ответ, добавьте также несколько комментариев о том, почему это решение решает OP-вопрос.
β.εηοιτ.βε
Вам не нужно использовать другой стиль форматирования строки только для добавления переменной ширины. Просто добавьте еще один заполнитель:"{:0{l}b}".format(num, l=length)
Martijn Pieters
-1

Вы можете использовать метод строкового синтаксиса Python: string.rjust (length, 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) верните x как '02' для месяца фев.

Аншул Гарг
источник
1
Проблема с zfill заключается в том, что он обрабатывает двоичную строку как строку и добавляет нули перед двоичным индикатором 'b' ... например, bin(14) дает `'0b1110'` и bin(14).zfill(8) дает `'000b1110'` not `'0b00001110'`, что и нужно
Шон