Перетворити рядок у двійковий у python


106

Мені потрібен спосіб отримати двійкове представлення рядка в python. напр

st = "hello world"
toBinary(st)

Чи є модуль якогось акуратного способу зробити це?


8
Яким ви очікуєте конкретно результатом?
— NPE

Під "двійковим" ви маєте на увазі тип 0101010 або внутрішній ordномер кожного символу (наприклад, шестигранник)?
— cdarke

Якщо припустити, що ви насправді маєте на увазі двійкові (нулі та одиниці), чи хочете ви двійкове представлення кожного символу (8 біт на символ) один за одним? наприклад, h - значення ascii 104, було б 01101000 у двійковій
— формі

Це питання було дано відповіді багато разів на StackOverflow: stackoverflow.com/questions/11599226 / ... stackoverflow.com/questions/8553310 / ...
— 0xcaff

можливий дублікат Convert Binary в ASCII і навпаки (Python)
— jfs

Відповіді:


124

Щось на зразок цього?

>>> st = "hello world"
>>> ' '.join(format(ord(x), 'b') for x in st)
'1101000 1100101 1101100 1101100 1101111 100000 1110111 1101111 1110010 1101100 1100100'

#using `bytearray`
>>> ' '.join(format(x, 'b') for x in bytearray(st, 'utf-8'))
'1101000 1100101 1101100 1101100 1101111 100000 1110111 1101111 1110010 1101100 1100100'

21
Або якщо ви хочете, щоб кожне двійкове число було 1 байт: '' .join (формат (ord (i), 'b'). Zfill (8) для i in st)
— ChrisProsser

5
Для повних байтів ви також можете використовувати ' '.join('{0:08b}'.format(ord(x), 'b') for x in st), що приблизно на 35% швидше, ніж zfill(8)рішення (принаймні, на моїй машині).
— макс

А як щодо перетворення символів, що більше одного байта, як β, наприклад, який, як мені здається, представлений 11001110 10110010внутрішньо?
— Сергій Бушманов

1
Я знаю, що це було розміщено давно, але як бути з символами, що не належать до ASCII?
— pkqxdd

48

Як більш пітонічний спосіб, ви можете спочатку перетворити рядок у байтовий масив, а потім використовувати binфункцію в межах map:

>>> st = "hello world"
>>> map(bin,bytearray(st))
['0b1101000', '0b1100101', '0b1101100', '0b1101100', '0b1101111', '0b100000', '0b1110111', '0b1101111', '0b1110010', '0b1101100', '0b1100100']

Або ви можете приєднатися до нього:

>>> ' '.join(map(bin,bytearray(st)))
'0b1101000 0b1100101 0b1101100 0b1101100 0b1101111 0b100000 0b1110111 0b1101111 0b1110010 0b1101100 0b1100100'

Зауважте, що в python3 потрібно вказати кодування для bytearrayфункції:

>>> ' '.join(map(bin,bytearray(st,'utf8')))
'0b1101000 0b1100101 0b1101100 0b1101100 0b1101111 0b100000 0b1110111 0b1101111 0b1110010 0b1101100 0b1100100'

Ви також можете використовувати binasciiмодуль у python 2:

>>> import binascii
>>> bin(int(binascii.hexlify(st),16))
'0b110100001100101011011000110110001101111001000000111011101101111011100100110110001100100'

hexlifyповернути шістнадцяткове представлення бінарних даних, тоді ви можете перетворити в int, вказавши 16 як його базу, а потім перетворити їх у двійкові bin.


5
Це не тільки пітонічно, але це "більш" правильно для багатобайтових рядків, що не належать до ASCII.
— Сергій Бушманов

Зауважимо лише, що (принаймні для поточної версії 3.7.4): (1) bytearrayочікує, що кодування (а не лише рядок) і (2) map(bin, ...)повернуть mapоб'єкт. Для першого пункту я використовую, наприклад, bob.encoding ('ascii') `, як запропонував @Tao. По-друге, вкажіть, використовуючи joinметод, як в інших прикладах @Kasramvd відобразить бажаний результат.
— Антуан

35

Нам просто потрібно його кодувати.

'string'.encode('ascii')

Для мене ( v3.7.4) це повертає bytesоб'єкт (з представленнями ascii кожного байту, якщо він є), і для того, щоб відобразити його бінарне представлення, мені потрібно bin, наприклад, з ' '.join(item[2:] for item in map(bin, 'bob'.encode('ascii')))(зверніть увагу, що 0bйого потрібно видалити на початку бінарного представлення кожного персонажа).
— Антуан

15

Ви можете отримати доступ до значень коду для символів у рядку за допомогою ord()вбудованої функції. Якщо вам потрібно буде відформатувати це у двійковому форматі, string.format()метод зробить цю роботу.

a = "test"
print(' '.join(format(ord(x), 'b') for x in a))

(Дякую Ешвіні Шадхарі за публікацію фрагмента коду.)

Хоча вищезазначений код працює в Python 3, це питання ускладнюється, якщо ви припускаєте будь-яке кодування, крім UTF-8. У Python 2 рядки є послідовностями байтів, а кодування ASCII передбачається за замовчуванням. У Python 3 рядки вважаються Unicode, і існує окремий bytesтип, який більше схожий на рядок Python 2. Якщо ви хочете припустити будь-яке кодування, крім UTF-8, вам потрібно буде вказати кодування.

У Python 3 ви можете зробити щось подібне:

a = "test"
a_bytes = bytes(a, "ascii")
print(' '.join(["{0:b}".format(x) for x in a_bytes]))

Відмінності між кодуванням UTF-8 та кодуванням ascii не будуть очевидними для простих буквено-цифрових рядків, але стануть важливими, якщо ви обробляєте текст, який включає символи, що не містяться в наборі символів ascii.


2

У версії Python 3.6 і вище ви можете використовувати f-string для форматування результату.

str = "hello world"
print(" ".join(f"{ord(i):08b}" for i in str))

01101000 01100101 01101100 01101100 01101111 00100000 01110111 01101111 01110010 01101100 01100100
  • Ліва сторона двокрапки, ord (i), є фактичним об'єктом, значення якого буде відформатоване та вставлено у висновок. Використання ord () дає точку коду базового 10 для одного символу str.

  • Права частина двокрапки - специфікатор формату. 08 означає ширину 8, 0 прокладений, а b функціонує як знак для виведення отриманого числа в базі 2 (двійкові).


1

Це оновлення для існуючих відповідей, які використовувались bytearray()і більше не можуть працювати таким чином:

>>> st = "hello world"
>>> map(bin, bytearray(st))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: string argument without an encoding

Тому що, як пояснено у посиланні вище, якщо джерелом є рядок, ви також повинні дати кодування :

>>> map(bin, bytearray(st, encoding='utf-8'))
<map object at 0x7f14dfb1ff28>

0
def method_a(sample_string):
    binary = ' '.join(format(ord(x), 'b') for x in sample_string)

def method_b(sample_string):
    binary = ' '.join(map(bin,bytearray(sample_string,encoding='utf-8')))


if __name__ == '__main__':

    from timeit import timeit

    sample_string = 'Convert this ascii strong to binary.'

    print(
        timeit(f'method_a("{sample_string}")',setup='from __main__ import method_a'),
        timeit(f'method_b("{sample_string}")',setup='from __main__ import method_b')
    )

# 9.564299999998184 2.943955828988692

method_b є значно ефективнішим при перетворенні в байтовий масив, оскільки він робить виклики функцій низького рівня, а не вручну перетворює кожен символ у ціле число, а потім перетворює це ціле число у його бінарне значення.


-1
a = list(input("Enter a string\t: "))
def fun(a):
    c =' '.join(['0'*(8-len(bin(ord(i))[2:]))+(bin(ord(i))[2:]) for i in a])
    return c
print(fun(a))

1
Чи хотіли б ви доповнити цю нечитабельну відповідь лише для коду деяким поясненням? Це допоможе боротися з помилковим уявленням про те, що StackOverflow - це послуга безкоштовного написання коду. У разі , якщо ви хочете , щоб поліпшити читаність, спробуйте Інформація , представлена тут: stackoverflow.com/editing-help
— Yunnosch
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.