Преобразовать число в двоичную строку - PullRequest
4 голосов
/ 31 марта 2009

Это лучший способ преобразовать число Python в шестнадцатеричную строку?

number = 123456789
hex(number)[2:-1].decode('hex')

Иногда это не работает и жалуется на строку нечетной длины, когда вы делаете 1234567890.

Пояснение:

Я перехожу из int в hex.

Кроме того, мне нужно сбежать.

IE: 1234567890 -> '\ x49 \ x96 \ x02 \ xd2' not '499602D2'

Кроме того, он должен иметь возможность принимать любое целое число Python. IE. нечто большее, чем Int.

Edit:

Вот лучшее решение, которое я пока собрал с поста Паоло и Девина.

def hexify(num):
    num = "%x" % num

    if len(num) % 2:
        num = '0'+num

    return num.decode('hex')

Ответы [ 7 ]

6 голосов
/ 31 марта 2009

Вы можете использовать форматирование строки :

>>> number = 123456789
>>> hex = "%X" % number
>>> hex
'75BCD15'
5 голосов
/ 31 марта 2009

Я не совсем уверен, что вы хотите, но вы смотрели на struct модуль?

С учетом

>>> hex(123456789)
'0x75bcd15'

Вы можете сделать:

>>> struct.pack('i', 123456789)
'\x15\xcd[\x07'

Обратите внимание, что '\x5b' == '['.

Кроме того, вы можете обратить вспять порядок байтов:

>>> struct.pack('>i', 123456789)
'\x07[\xcd\x15'

Редактировать: Я не уверен, что вы подразумеваете под "больше, чем длинная", поскольку лонг AFAIK в python не ограничен (кроме памяти) Тем не менее, вы можете иметь дело с большими целыми числами, просто разделив и объединив. например Дано:

>>> n = 123456789012345678901234567890

цель:

>>> hex(n)
'0x18ee90ff6c373e0ee4e3f0ad2L'

Итак:

>>> s = ''
>>> while n >= 2**32:
...  n, r = divmod(n, 2**32)
...  s = struct.pack('>l', r) + s
... 
>>> s = struct.pack('>l', n) + s

Обратите внимание, что s соответствует результату hex(n) выше:

>>> s
'\x00\x00\x00\x01\x8e\xe9\x0f\xf6\xc3s\xe0\xeeN?\n\xd2'
1 голос
/ 03 июня 2011
'{0:b}'.format( number )

см. http://docs.python.org/library/string.html

1 голос
/ 31 марта 2009

Иногда это не работает и жалуется на строку нечетной длины, когда вы делаете 1234567890.

Потому что это не имеет смысла. Как вы помещаете «AAB» в пространство, которое занимает 2 или 4 цифры? Каждый байт состоит из двух шестнадцатеричных символов. Если у вас нечетное количество шестнадцатеричных символов, желаемый результат неоднозначен. Вы хотите, чтобы это был эквивалент 0AAB или AAB0? Если вы знаете, какой из них вам нужен, просто добавьте этот символ в нужное место перед расшифровкой.

т.е. (('0' + foo) if len(foo) % 2 else foo).decode('hex') где foo - строка формы, возвращенная %x.

0 голосов
/ 29 июня 2010

один из самых надежных способов для произвольных чисел - использовать модуль «массив» следующим образом:

from array import array
binArr = array('B')

while(data):
    d = data & 0xFF
    binArr.append(d)
    data >>= 8

hexStr = binArr.tostring()
0 голосов
/ 31 марта 2009

Если вы знаете, какой длины должны быть ваши выходные строки, форматирование строк будет работать. Например, чтобы получить четырехсимвольные строки, вам нужно отформатировать длину восемь:

>>> "{0:08x}".format(123456789).decode("hex")
'\x07[\xcd\x15'
>>> "{0:08x}".format(1234567890).decode("hex")
'I\x96\x02\xd2'

Это приведет к добавлению нулей, если ваш номер не «заполняет» строку. Например, с шестизначными строками:

>>> "{0:012x}".format(123456789).decode("hex")
'\x00\x00\x07[\xcd\x15'
>>> "{0:012x}".format(1234567890).decode("hex")
'\x00\x00I\x96\x02\xd2'

Edit:

Чтобы «определить» длину целевых строк, вы можете использовать функцию math.log:

>>> def int2str(n):
        l = int(math.ceil(math.log(n, 256) / 2) * 4)
        return ("{0:0{1}x}").format(n, l).decode("hex")

>>> int2str(123456789)
'\x07[\xcd\x15'
>>> int2str(1234567890)
'I\x96\x02\xd2'
0 голосов
/ 31 марта 2009

Как уже упоминал Паоло, форматирование строк - это путь. Обратите внимание, что вы можете выбирать между строчными и прописными буквами:

>>> hex = lambda n: '%X' % n
>>> hex(42)
'2A'
>>> hex = lambda n: '%x' % n
>>> hex(42)
'2a'
>>> def escaped(n):
...     s = hex(n)
...     if len(s) & 1:
...          s = '0' + s
...     return ''.join(chr(int(s[i:i + 2], 16)) for i in range(0, len(s), 2))
...
>>> escaped(123)
'{'
>>> escaped(1234)
'\x04\xd2'
>>> escaped(12348767655764764654764445473245874398787989879879873)
'!\x01^\xa4\xdf\xdd(l\x9c\x00\\\xfa*\xf3\xb4\xc4\x94\x98\xa9\x03x\xc1'

Обратите внимание, что экранированный добавляет начальный ноль в случае нечетного числа шестнадцатеричных цифр. Это решение работает для строк любой длины.

...