2016-08-24 4 views
1

От ввода 0x1234 Мне нужно вывести: 0b0001_0010_0011_0100.python конвертировать шестнадцатеричную строку в формируемую двоичную строку

Я могу придумать все плохие способы сделать это, но для чего это самый пифонический способ.

Я могу с легкостью преобразовать в строку буфера (bin(int('0x1234', 16)), но это только дает мне 0001001000110100. Мне нужен _ между кусками.

спасибо.

+0

Какие способы вы пытались до сих пор? – smarx

+0

Знаете ли вы о циклах, разрезаниях и списках? Если вы это сделаете, я думаю, вы можете сделать это в строке или двух. –

+0

Я преобразовал строку в бит-массив, а затем зациклил над битным массивом и добавив «_» на каждый четвертый элемент, а затем распечатал его. Очень похоже на функцию c. – Romeo

ответ

3

шестигранной отображает одну цифру в один грызть ... так что вы можете сделать это довольно легко с таблицей перекодировки

hex2bin_map = { 
    "0":"0000", 
    "1":"0001", 
    "2":"0010", 
    "3":"0011", 
    "4":"0100", 
    "5":"0101", 
    "6":"0110",  
    "7":"0111", 
    "8":"1000", 
    "9":"1001", 
    "A":"1010", 
    "B":"1011", 
    "C":"1100", 
    "D":"1101", 
    "E":"1110", 
    "F":"1111", 
} 
hex_num="1234" 
print "_".join(hex2bin_map[i] for i in hex_num) 
# 0001_0010_0011_0100 

это не будет, как немногословен, как другой ответ (ов) я уверен ... но его вероятно, наиболее эффективный ... и его приятный дарг легко читается (т. е. вам не нужно беспокоиться о шаблоне группового кода zip или регулярных выражений, которые должны смущать новых программистов)

+0

Мне нравится, что это позволяет избежать перекрестного перехода из строки -> number -> обратно в строку. –

+0

plus dict lookups - O (1) ... это действительно преимущество .... str-> num-> str действительно довольно быстрая операция –

+0

Спасибо !. в этом есть смысл. – Romeo

1

Не уверен, что, если есть лучший способ, но это работает (в предположении, что числа всегда 16-бит):

# Takes a hex-encoded 16-bit number and returns a binary representation with 
# leading zeros and underscores as a nibble separator. 
def binary_representation(string): 
    return '0b' + '_'.join(
     ''.join(nibble) for nibble in zip(*([iter('{:>016b}'.format(int(string, 16)))]*4))) 

assert binary_representation('0x1234') == '0b0001_0010_0011_0100' 

zip трюк хороший один, который исходит от grouper example in the Python docs. Этот вызов по существу испускает [('0', '0', '0', '1'), ('0', '0', '1', '0'), ...]. Оттуда вам просто нужно перевернуть каждый кусок в одну строку, а затем присоединить их все с подчеркиваниями.

Другим интересным битом здесь является формат {:>016b}, который дает вам выровненное по правому краю двоичное представление числа. Если вам нужно поддерживать разные размеры чисел, это часть, которую вам нужно будет изменить.

UPDATE

Учитывая, что ваш номер начинается как строки, такой подход еще проще, вдохновленный @ ответ Joran, но без таблицы перекодировки.

def binary_representation(string): 
    return '0b' + '_'.join(['{:>04b}'.format(int(d, 16)) for d in string[2:]]) 
+0

Спасибо. который видит работу. – Romeo

1

В качестве альтернативы generic sequence chunking, для строк, вы можете использовать регулярное выражение для группы и заменить:

>>> '0b' + re.sub(r'(\d{4})(?!$)', r'\1_', format(int('0x1234', 16), '016b')) 
'0b0001_0010_0011_0100' 

В Python 3.6, вы сможете сделать это с помощью спецификатора формата (см PEP 515)

'0b' + format(int('0x1234', 16), '016_b') 

или, если вы предпочитаете:

'0b{:016_b}'.format(int('0x1234', 16)) 
Смежные вопросы