Python int до двійкового рядка?


529

Чи існують консервовані методи Python для перетворення цілого (або довгого) у бінарний рядок в Python?

У Google існує безліч функцій dec2bin () ... Але я сподівався, що зможу використовувати вбудовану функцію / бібліотеку.


Для зворотного взяття, для чистого алгоритму обробки рядків, дивіться це .
CopyPasteIt

Відповіді:


750

Метод формату рядка Python може приймати специфікацію формату.

>>> "{0:b}".format(37)
'100101'

Форматування специфікацій документів для Python 2

Форматування специфікацій документів для Python 3


86
str.format()просто відформатувати одне значення є надмірним. Ідіть прямо до format()функції : format(n, 'b'). Немає необхідності розбирати заповнювач та приєднувати його до аргументу, перейдіть безпосередньо до самої операції форматування значення. Використовуйте лише в тому str.format()випадку, якщо вам потрібно розмістити відформатований результат у більш довгій строці (наприклад, використовувати його як шаблон).
Martijn Pieters

29
@mike: Або використовувати специфікацію форматування. Додайте кількість розрядів, що ведуть 0до рядка форматування: format(10, '016b')формати до 16 цифр з провідними нулями.
Martijn Pieters

У цьому випадку 0ін "{0:b}"може бути відпущено ні? Я маю на увазі, що у випадку, коли форматується лише одне число, це правильно "{:b}", чи не так?
tomasyany

1
зазвичай можна використовувати 4/8 / ... бітове представлення:"{:08b}".format(37)
Sparkler

2
f "{37: b}" в Python3.7 або пізнішої версії.
DA

471

Якщо ви шукаєте bin()як еквівалент hex(), він був доданий у python 2.6.

Приклад:

>>> bin(10)
'0b1010'

66
Зауважте також, що це зробити швидше str(bin(i))[2:](0,369 секунди на 1000000оп), ніж "{0:b}".format(i)(0,721с на 1000000опс)
mVChr

64
@mVChr, якщо хтось перетворює числа у бінарне представлення ASCII, я дуже сподіваюся, що швидкість не має значення.
Нік Т

29
@mVChr: str.format()це все-таки неправильний інструмент, який ви б format(i, 'b')замість цього використали . Враховуйте, що це також дає вам опції прокладки та вирівнювання; format(i, '016b')відформатувати на 16-бітове бінарне число, заповнене нулем. Щоб зробити те ж саме, bin()вам потрібно було б додати str.zfill()дзвінок: bin(i)[2:].zfill(16)( дзвонити не потрібно str()!). format()читабельність та гнучкість (динамічне форматування набагато складніше bin()) великі компроміси, не оптимізуйте продуктивність, якщо вам не доведеться, до цього часу оптимізуйте для ремонту.
Martijn Pieters

Що означає [2:]?
zero_cool

4
Звичайно, з python 3.6+ і тепер ви можете користуватися f"{37:b}".
Люк Девіс

63

Python на насправді робить що - то вже побудований в для цього, здатність робити такі операції, як '{0:b}'.format(42), який дасть вам бітовий шаблон (в рядку) для 42, або 101010.


Для більш загальної філософії жодна мова чи бібліотека не дадуть користувачу базувати все, що вони бажають. Якщо ви працюєте в середовищі, яке не забезпечує саме те, що вам потрібно, вам слід збирати фрагменти коду, коли ви розробляєте, щоб переконатися, що вам ніколи не потрібно писати одне і те ж двічі. Наприклад, наприклад, псевдо-код:

define intToBinString, receiving intVal:
    if intVal is equal to zero:
        return "0"
    set strVal to ""
    while intVal is greater than zero:
        if intVal is odd:
            prefix "1" to strVal
        else:
            prefix "0" to strVal
        divide intVal by two, rounding down
    return strVal

який побудує ваш двійковий рядок на основі десяткового значення. Просто майте на увазі , що це родове трохи псевдо-коду , який не може бути найбільш ефективний спосіб зробити це , хоча, з ітерацій ви , здається, пропонує, це не матиме великого значення. Це насправді просто призначене як настанова про те, як це можна зробити.

Загальна ідея полягає у використанні коду з (у порядку уподобання):

  • мова або вбудовані бібліотеки.
  • сторонні бібліотеки з відповідними ліцензіями.
  • власну колекцію.
  • щось нове, що вам потрібно написати (і зберегти у власній колекції на потім).

1
Деякі хороші поради в цій відповіді. Лише дуже погано, що код непотрібно повільний. Ви пропонуєте O (N ^ 2) альго, де O (N) зробив би. Проблемна частина знаходиться в рядках s = "1" + sі s = "0" + s. Кожен робить непотрібну копію s. Ви повинні повернути рядок безпосередньо перед поверненням.
Андреас Магнуссон

@Andreas, те, що я запропонував, було використовувати '{0:b}'.format(42), повільний метод був просто прикладом того, як це зробити загально, що може бути, а може і не бути O (n ^ 2) залежно від фактичної мови, що використовується. Це схоже лише на Python, оскільки Python є ідеальною мовою псевдокоду, тому я зміню це, щоб зробити його зрозумілим.
paxdiablo

Насправді це була б досить езотерична мова, де s = "1" + sне було O (N), коли sце рядковий тип. Можливо, мова, де всі рядки зберігаються назад або кожен символ є вузлом у пов'язаному списку? Для будь-якої типової мови рядок - це в основному масив символів. У цьому випадку для префіксації рядка потрібно зробити копію, як ще ви збираєтесь поставити символ перед іншими символами?
Андреас Магнуссон

Я можу легко передбачити тип рядка, який складається з блоку пам'яті, де рядок є правильно виправданим у цьому блоці, і зміщення його початкового символу. Щоб встановити префікс, ви просто зменшите зсув і збережіть його там. Так, це було б езотеричним, але мені мало сенсу сперечатися про можливі проблеми з реальним світом з невеликим псевдокодом, тим більше, що ви, швидше за все, не матимете кілька десятків біт / ітерацій. Навіть сильно злісний сорт бульбашок є адекватним, якщо розмір ваших даних невеликий :-) У будь-якому випадку я додам примітку про ефективність.
paxdiablo

Звичайно, якщо важлива ефективність, ви, мабуть, не обираєте пітон для початку. Але, на моєму досвіді, досить часто трапляється, що код, написаний наївно за допомогою альго O (N²) і перевірений невеликим набором даних, швидко звикає до набагато більшого набору даних, оскільки "він, здається, працює". Тоді раптом у вас з’явиться код, на який потрібно зайняти години, які при фіксації можуть зайняти лише секунди. O (N²) альго є підступними, оскільки вони, здається, працюють деякий час, але коли ваші дані масштабують, їх немає, і тоді хлопець, який їх написав, кинув, і ніхто не знає, чому все триває назавжди.
Андреас Магнуссон

41

Якщо ви хочете текстове подання без префікса 0b, ви можете використовувати це:

get_bin = lambda x: format(x, 'b')

print(get_bin(3))
>>> '11'

print(get_bin(-3))
>>> '-11'

Коли ви хочете n-бітове представлення:

get_bin = lambda x, n: format(x, 'b').zfill(n)
>>> get_bin(12, 32)
'00000000000000000000000000001100'
>>> get_bin(-12, 32)
'-00000000000000000000000000001100'

Якщо ви хочете мати функцію:

def get_bin(x, n=0):
    """
    Get the binary representation of x.

    Parameters
    ----------
    x : int
    n : int
        Minimum number of digits. If x needs less digits in binary, the rest
        is filled with zeros.

    Returns
    -------
    str
    """
    return format(x, 'b').zfill(n)

5
Або просто використовувати format(integer, 'b'). bin()являє собою інструмент налагодження, спеціально спрямований на створення бітерального синтаксису бінарних цілих чисел Python , format()призначений для отримання конкретних форматів.
Martijn Pieters

1
@MartijnPieters Дякую вам дуже за те, що ви згадали про це. Я налагодив розчинення. Звідки ви знаєте, що bin()це інструмент налагодження, спрямований на створення синтаксису бінарного цілого чисел Python з буквами? Я не міг цього знайти в документації.
Мартін Тома

2
З документації: Результат - допустимий вираз Python . Його мета - створити вираз Python, а не створювати уявлення кінцевих користувачів. Те саме стосується oct()і hex().
Martijn Pieters

4
Більше альтернатив: Якщо ви збираєтеся зробити ширину динамічною, замість цього str.zfill()ви можете використовувати str.format()або format()з другим динамічним аргументом: '{0:0{1}b}'.format(x, n)або format(b, '0{}b'.format(n)).
Martijn Pieters

@MartijnPieters Вау, дуже дякую за цей вклад! Я не знав, що це можливо з форматом. Однак я думаю, що мою сьогоднішню відповідь zfillлегше прочитати та зрозуміти, ніж динамічний другий аргумент, тому я буду її тримати.
Мартін Тома

37

В якості довідки:

def toBinary(n):
    return ''.join(str(1 & int(n) >> i) for i in range(64)[::-1])

Ця функція може конвертувати додатне ціле число великим 18446744073709551615, поданим у вигляді рядка '1111111111111111111111111111111111111111111111111111111111111111'.

Він може бути модифікований для подання набагато більшого цілого числа, хоча він може бути не таким зручним, як "{0:b}".format()або bin().


@GarethDavidson, яка це версія? Якщо це явно сказано, це може бути корисним у майбутньому при його гугленні.
Вовк

Думаю, це була версія 2.7. Я сумніваюсь, що це спрацює в 3.x
Гарет Девідсон

17

Простий спосіб зробити це - використовувати формат рядків, див. Цю сторінку .

>> "{0:b}".format(10)
'1010'

І якщо ви хочете мати фіксовану довжину двійкового рядка, ви можете скористатися цим:

>> "{0:{fill}8b}".format(10, fill='0')
'00001010'

Якщо потрібне доповнення двох, то можна використовувати наступний рядок:

'{0:{fill}{width}b}'.format((x + 2**n) % 2**n, fill='0', width=n)

де n - ширина двійкового рядка.



14

одноводковий з лямбда :

>>> binary = lambda n: '' if n==0 else binary(n/2) + str(n%2)

тест:

>>> binary(5)
'101'



Редагувати :

але потім :(

t1 = time()
for i in range(1000000):
     binary(i)
t2 = time()
print(t2 - t1)
# 6.57236599922

в порівнянні з

t1 = time()
for i in range(1000000):
    '{0:b}'.format(i)
t2 = time()
print(t2 - t1)
# 0.68017411232

що повертає '', хоча 0. Чи не було б нормальне представлення для 0 "0"?
dietbacon

якщо ви хочете побачити, що 0 :), ви можете замінити ''на '0', але це додасть провідний 0 для будь-якого числа.
Азіз Альто

11

Короткий зміст альтернативних варіантів:

n=42
assert  "-101010" == format(-n, 'b')
assert  "-101010" == "{0:b}".format(-n)
assert  "-101010" == (lambda x: x >= 0 and str(bin(x))[2:] or "-" + str(bin(x))[3:])(-n)
assert "0b101010" == bin(n)
assert   "101010" == bin(n)[2:]   # But this won't work for negative numbers.

Співавтори включають Джона Фуші , Тун Нгуєна , mVChr , Мартіна Тома . та Мартійн Пітерс.


6
str.format()просто відформатувати одне значення є надмірним. Ідіть прямо до format()функції: format(n, 'b'). Не потрібно розбирати заповнювач місця та порівнювати його з таким аргументом.
Martijn Pieters

10

В якості попередніх відповідей в основному використовується формат (), ось реалізація f-string.

integer = 7
bit_count = 5
print(f'{integer:0{bit_count}b}')

Вихід:

00111

Для зручності тут посилання на документи python для форматованих рядкових літералів: https://docs.python.org/3/reference/lexical_analysis.html#f-strings .



5

Використовуючи numpy pack / unpackbits, вони є вашими найкращими друзями.

Examples
--------
>>> a = np.array([[2], [7], [23]], dtype=np.uint8)
>>> a
array([[ 2],
       [ 7],
       [23]], dtype=uint8)
>>> b = np.unpackbits(a, axis=1)
>>> b
array([[0, 0, 0, 0, 0, 0, 1, 0],
       [0, 0, 0, 0, 0, 1, 1, 1],
       [0, 0, 0, 1, 0, 1, 1, 1]], dtype=uint8)

Питання стосується представлення рядків . Але все-таки це було саме те, що я шукав, не переходячи через рядок спочатку! :)
Том Хейл

DOCO каже: розпаковує елементи uint8масиву в вихідний масив довічного-значної. Так добре для значень до 255.
Том Хейл,

5

Для тих із нас, кому потрібно перетворити підписані цілі числа (діапазон -2 ** (цифри-1) до 2 ** (цифри-1) -1) до дворядних доповнюючих рядків 2, це працює:

def int2bin(integer, digits):
if integer >= 0:
    return bin(integer)[2:].zfill(digits)
else:
    return bin(2**digits + integer)[2:]

Це дає:

>>> int2bin(10, 8)
'00001010'
>>> int2bin(-10, 8)
'11110110'
>>> int2bin(-128, 8)
'10000000'
>>> int2bin(127, 8)
'01111111'


4

Ще одне рішення з іншим алгоритмом, використовуючи побітові оператори.

def int2bin(val):
    res=''
    while val>0:
        res += str(val&1)
        val=val>>1     # val=val/2 
    return res[::-1]   # reverse the string

Більш швидка версія без обертання рядка.

def int2bin(val):
   res=''
   while val>0:
       res = chr((val&1) + 0x30) + res
       val=val>>1    
   return res 

Друга версія, безумовно, не швидша, оскільки ви закінчите щось на зразок алгоритму O (N ^ 2) замість O (N). Я бачив такі речі, як це вбиває додаток (що залежить від продуктивності), оскільки розробник думав зробити додатковий пропуск в кінці повільніше, ніж робити якісь додаткові речі в першому циклі. Після фіксації час роботи тривав від кількох днів до секунд.
Андреас Магнуссон

4
def binary(decimal) :
    otherBase = ""
    while decimal != 0 :
        otherBase  =  str(decimal % 2) + otherBase
        decimal    //=  2
    return otherBase

print binary(10)

вихід:

1010



3

Ось код, який я щойно реалізував. Це не метод, але ви можете використовувати його як готову до використання функцію !

def inttobinary(number):
  if number == 0:
    return str(0)
  result =""
  while (number != 0):
      remainder = number%2
      number = number/2
      result += str(remainder)
  return result[::-1] # to invert the string

3

ось просте рішення, використовуючи fucntion divmod (), який повертає нагадування та результат поділу без дробу.

def dectobin(number):
    bin = ''
    while (number >= 1):
        number, rem = divmod(number, 2)
        bin = bin + str(rem)
    return bin

Потреби налагодження. Виклик dectobin(10)призвів до '0101'
Нейт


3

numpy.binary_repr(num, width=None)

Приклади із посилання на документацію вище:

>>> np.binary_repr(3)
'11'
>>> np.binary_repr(-3)
'-11'
>>> np.binary_repr(3, width=4)
'0011'

Доповнення двох повертається, коли вхідне число від'ємне і вказана ширина:

>>> np.binary_repr(-3, width=3)
'101'
>>> np.binary_repr(-3, width=5)
'11101'

2

Дещо подібне рішення

def to_bin(dec):
    flag = True
    bin_str = ''
    while flag:
        remainder = dec % 2
        quotient = dec / 2
        if quotient == 0:
            flag = False
        bin_str += str(remainder)
        dec = quotient
    bin_str = bin_str[::-1] # reverse the string
    return bin_str 

2

Ось ще один спосіб використання звичайної математики, без циклів, лише рекурсії. (Тривіальний випадок 0 нічого не повертає).

def toBin(num):
  if num == 0:
    return ""
  return toBin(num//2) + str(num%2)

print ([(toBin(i)) for i in range(10)])

['', '1', '10', '11', '100', '101', '110', '111', '1000', '1001']

2

Калькулятор з усіма необхідними функціями для DEC, BIN, HEX: (зроблено та протестовано з Python 3.5)

Ви можете змінити вхідні тестові номери та отримати перетворені.

# CONVERTER: DEC / BIN / HEX

def dec2bin(d):
    # dec -> bin
    b = bin(d)
    return b

def dec2hex(d):
    # dec -> hex
    h = hex(d)
    return h

def bin2dec(b):
    # bin -> dec
    bin_numb="{0:b}".format(b)
    d = eval(bin_numb)
    return d,bin_numb

def bin2hex(b):
    # bin -> hex
    h = hex(b)
    return h

def hex2dec(h):
    # hex -> dec
    d = int(h)
    return d

def hex2bin(h):
    # hex -> bin
    b = bin(h)
    return b


## TESTING NUMBERS
numb_dec = 99
numb_bin = 0b0111 
numb_hex = 0xFF


## CALCULATIONS
res_dec2bin = dec2bin(numb_dec)
res_dec2hex = dec2hex(numb_dec)

res_bin2dec,bin_numb = bin2dec(numb_bin)
res_bin2hex = bin2hex(numb_bin)

res_hex2dec = hex2dec(numb_hex)
res_hex2bin = hex2bin(numb_hex)



## PRINTING
print('------- DECIMAL to BIN / HEX -------\n')
print('decimal:',numb_dec,'\nbin:    ',res_dec2bin,'\nhex:    ',res_dec2hex,'\n')

print('------- BINARY to DEC / HEX -------\n')
print('binary: ',bin_numb,'\ndec:    ',numb_bin,'\nhex:    ',res_bin2hex,'\n')

print('----- HEXADECIMAL to BIN / HEX -----\n')
print('hexadec:',hex(numb_hex),'\nbin:    ',res_hex2bin,'\ndec:    ',res_hex2dec,'\n')

2

Для обчислення двійкових чисел:

print("Binary is {0:>08b}".format(16))

Для обчислення шістнадцяткових знаків числа :

print("Hexa Decimal is {0:>0x}".format(15))

Обчислити всі двійкові не до 16 ::

for i in range(17):
   print("{0:>2}: binary is {0:>08b}".format(i))

Для обчислення шістнадцяткових знаків немає до 17

 for i in range(17):
    print("{0:>2}: Hexa Decimal is {0:>0x}".format(i))
##as 2 digit is enogh for hexa decimal representation of a number

1

Якщо ви готові відмовитися від "чистого" Python, але отримаєте багато вогневої сили, є Sage - приклад тут :

sage: a = 15
sage: a.binary()
'1111'

Ви помітите, що він повертається як рядок, тому використовуйте його як число, яке ви хочете зробити на зразок чогось

sage: eval('0b'+b)
15

1
try:
    while True:
        p = ""
        a = input()
        while a != 0:
            l = a % 2
            b = a - l
            a = b / 2
            p = str(l) + p
        print(p)
except:
    print ("write 1 number")

6
Ви можете додати пояснення до того, що ви там робили.
Artless

1

Я знайшов метод, що використовує матричну операцію для перетворення десяткових у двійкові.

import numpy as np
E_mat = np.tile(E,[1,M])
M_order = pow(2,(M-1-np.array(range(M)))).T
bindata = np.remainder(np.floor(E_mat /M_order).astype(np.int),2)

Eвводиться десяткові дані, Mє двійкові порядки. bindataє вихідними двійковими даними, які є у форматі 1 бінарною матрицею M.


0

Ось простий бінарний до десятковий перетворювач, який постійно цикли

t = 1
while t > 0:
    binaryNumber = input("Enter a binary No.")
    convertedNumber = int(binaryNumber, 2)

    print(convertedNumber)

print("")

Це зворотний порядок того, чого хоче ОП. Вони шукають int to binary. Ви надаєте двійковий код до int.
Сесілія

0

Це моя відповідь, це працює добре ..!

def binary(value) :
    binary_value = ''
    while value !=1  :
        binary_value += str(value%2)
        value = value//2
    return '1'+binary_value[::-1]

Що робити, якщо ви передаєте значення 0? Наприклад binary(0), ви отримаєте те, що очікуєте?
Андреас Магнуссон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.