Шестнадцатеричная строка со знаком int в Python 3.2? - PullRequest
17 голосов
/ 18 июля 2011

Как мне преобразовать шестнадцатеричную строку в int со знаком в Python 3.2?

Лучшее, что я могу придумать, это

h = '9DA92DAB'
b = bytes(h, 'utf-8')
ba = binascii.a2b_hex(b)
print(int.from_bytes(ba, byteorder='big', signed=True))

Есть ли более простой способ?Без подписи это намного проще: int (h, 16)

Кстати, вопрос возник из-за itunes persistent id - версия xml музыкальной библиотеки и шестнадцатеричная версия iTunes

Ответы [ 5 ]

34 голосов
/ 18 июля 2011

В дополнении n-бит два биты имеют значение:

бит 0 = 2 0
бит 1 = 2 1
бит n-2 = 2 n-2
бит n-1 = -2 n-1

Но бит n-1 имеетзначение 2 n-1 , если оно не подписано, поэтому число слишком велико: 2 n .Вычтите 2 n , если установлен бит n-1:

>>> def twos_complement(hexstr,bits):
...     value = int(hexstr,16)
...     if value & (1 << (bits-1)):
...         value -= 1 << bits
...     return value
...
>>> twos_complement('FFFE',16)
-2
>>> twos_complement('7FFF',16)
32767
>>> twos_complement('7F',8)
127
>>> twos_complement('FF',8)
-1
5 голосов
/ 18 июля 2011
import struct

Для Python 3 (с помощью комментариев):

h = '9DA92DAB'
struct.unpack('>i', bytes.fromhex(h))

Для Python 2:

h = '9DA92DAB'
struct.unpack('>i', h.decode('hex'))

или, если это порядковый номер:

h = '9DA92DAB'
struct.unpack('<i', h.decode('hex'))
1 голос
/ 06 октября 2017

Это очень поздний ответ, но здесь есть функция, чтобы сделать выше.Это будет продолжаться на любую длину, которую вы предоставите.Отнесите часть этого к другому SO-ответу (я потерял ссылку, поэтому предоставьте ее, если найдете).

1 голос
/ 05 сентября 2016

Это работает для 16-битных целых чисел, вы можете расширить для 32-битных целых. Он использует базовое определение 2 дополненных чисел со знаком. Также обратите внимание, что xor с 1 - это то же самое, что двоичное отрицание.

# convert to unsigned
x = int('ffbf', 16) # example (-65)
# check sign bit
if (x & 0x8000) == 0x8000:
    # if set, invert and add one to get the negative value, then add the negative sign
    x = -( (x ^ 0xffff) + 1)
1 голос
/ 13 февраля 2015

Вот общая функция, которую вы можете использовать для гексагона любого размера:

import math

# hex string to signed integer
def htosi(val):
    uintval = int(val,16)
    bits = 4 * (len(val) - 2)
    if uintval >= math.pow(2,bits-1):
        uintval = int(0 - (math.pow(2,bits) - uintval))
    return uintval

И использовать его:

h = str(hex(-5))
h2 = str(hex(-13589))
x = htosi(h)
x2 = htosi(h2)
...