Python'da dizeyi ikiliye dönüştür


106

Python'da bir dizenin ikili temsilini elde etmek için bir yola ihtiyacım var. Örneğin

st = "hello world"
toBinary(st)

Bunu yapmanın düzgün bir yolu var mı?


8
Çıktının özellikle ne olmasını bekliyorsunuz?
NPE

"İkili" ile, 0101010 türünü mi yoksa ordher karakterin inal sayısını mı (ör. Onaltılık) kastediyorsunuz ?
cdarke

Aslında ikili (sıfırlar ve birler) demek istediğinizi varsayarsak, her karakterin birbiri ardına ikili temsilini (karakter başına 8 bit) istiyor musunuz? örneğin h ascii değeridir 104, ikili değerde 01101000 olur
ChrisProsser

Bu soru stackoverflow'da birçok kez yanıtlanmıştır: stackoverflow.com/questions/11599226/… stackoverflow.com/questions/8553310/…
0xcaff

Yanıtlar:


124

Bunun gibi bir şey mi?

>>> 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
Veya her ikili sayının 1 bayt olmasını istiyorsanız: '' .join (format (ord (i), 'b'). Zfill (8) for i in st)
ChrisProsser

5
Tam baytlar için ' '.join('{0:08b}'.format(ord(x), 'b') for x in st), zfill(8)çözümden yaklaşık% 35 daha hızlı olan (en azından benim makinemde) kullanabilirsiniz.
en fazla

βÖrneğin, bana 11001110 10110010dahili olarak temsil edilen gibi görünen birden fazla baytlık karakterleri dönüştürmeye ne dersiniz ?
Sergey Bushmanov

1
Bunun uzun zaman önce yayınlandığını biliyorum, peki ya ASCII olmayan karakterler?
pkqxdd

48

Daha pitonik bir yol olarak, önce dizenizi bayt dizisine dönüştürebilir ve ardından biniçindeki işlevi kullanabilirsiniz map:

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

Ya da katılabilirsiniz:

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

Python3'tebytearray işlev için bir kodlama belirtmeniz gerektiğini unutmayın :

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

binasciiModülü python 2'de de kullanabilirsiniz :

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

hexlifyikili verinin onaltılık gösterimini döndürür, sonra 16'yı taban olarak belirterek int'e dönüştürebilir ve ardından bunu ikiliye dönüştürebilirsiniz bin.


5
Sadece bu daha fazla pitonik değil, aynı zamanda çok baytlı ASCII olmayan dizeler için "daha" doğrudur.
Sergey Bushmanov

Sadece (en azından mevcut sürüm için 3.7.4): (1) bytearraybir kodlama beklediğini (sadece bir dizge değil) ve (2) nesneyi map(bin, ...)döndüreceğini unutmayın map. İlk nokta için, bob@Tao'nun önerdiği gibi örneğin .encoding ('ascii') 'kullanıyorum. İkinci joinolarak, diğer @Kasramvd örneklerinde olduğu gibi yöntemi kullanarak işaretleyin, istenen sonucu gösterecektir.
Antoine

36

Sadece onu kodlamamız gerekiyor.

'string'.encode('ascii')

Benim için ( v3.7.4), bu bir bytesnesne döndürür (varsa, her baytın ascii temsilleriyle) ve ikili gösterimini görüntülemek için bin, örneğin ' '.join(item[2:] for item in map(bin, 'bob'.encode('ascii')))( 0bikili temsilin başında kaldırılması gereken nota) ihtiyacım var. her karakterin).
Antoine

15

Yerleşik ord()işlevi kullanarak dizenizdeki karakterlerin kod değerlerine erişebilirsiniz . Daha sonra bunu ikili olarak biçimlendirmeniz gerekirse, string.format()yöntem işi yapacaktır.

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

(Bu kod parçasını gönderdiği için Ashwini Chaudhary'ye teşekkürler.)

Yukarıdaki kod Python 3'te çalışırken, UTF-8 dışında herhangi bir kodlama varsayıyorsanız, bu konu daha karmaşık hale gelir. Python 2'de dizeler bayt dizileridir ve ASCII kodlaması varsayılan olarak varsayılır. Python 3'te, dizelerin Unicode olduğu varsayılır ve bytesdaha çok Python 2 dizesi gibi davranan ayrı bir tür vardır. UTF-8 dışında herhangi bir kodlamayı varsaymak isterseniz, kodlamayı belirtmeniz gerekir.

Python 3'te şöyle bir şey yapabilirsiniz:

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

UTF-8 ve ascii kodlaması arasındaki farklar, basit alfasayısal dizeler için açık olmayacak, ancak ascii karakter setinde olmayan karakterleri içeren metinleri işliyorsanız önemli hale gelecektir.


2

Python 3.6 ve sonraki sürümlerinde sonucu biçimlendirmek için f-string kullanabilirsiniz.

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

01101000 01100101 01101100 01101100 01101111 00100000 01110111 01101111 01110010 01101100 01100100
  • Kolonun sol tarafı ord (i), değeri biçimlendirilecek ve çıktıya eklenecek gerçek nesnedir. Ord () kullanmak size tek bir str karakteri için temel 10 kod noktasını verir.

  • İki nokta üst üste işaretinin sağ tarafı, biçim belirleyicisidir. 08, genişlik 8, 0 dolgulu anlamına gelir ve b, sonuçtaki sayıyı 2 tabanında (ikili) çıkarmak için bir işaret olarak işlev görür.


1

Bu, kullanılan bytearray()ve artık bu şekilde çalışamayan mevcut cevaplar için bir güncellemedir :

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

Çünkü, yukarıdaki bağlantıda açıklandığı gibi, eğer kaynak bir dizge ise, kodlamayı da vermelisiniz :

>>> 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, bir bayt dizisine dönüştürmede önemli ölçüde daha etkilidir, çünkü her karakteri manuel olarak bir tam sayıya dönüştürmek ve ardından bu tamsayıyı ikili değerine dönüştürmek yerine düşük düzeyli işlev çağrıları yapar.


-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
Bu yalnızca okunamayan kod yanıtını bir açıklama ile artırmak ister misiniz? Bu, StackOverflow'un ücretsiz bir kod yazma hizmeti olduğu yanılgısıyla mücadeleye yardımcı olur. Okunabilirliği iyileştirmek istemeniz durumunda, burada sağlanan bilgileri deneyin: stackoverflow.com/editing-help
Yunnosch
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.