Ответ 1
x = int(h,16)
if x > 0x7FFFFFFF:
x -= 0x100000000
Как преобразовать шестнадцатеричную строку в подписанный 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))
Есть ли более простой способ? Unsigned намного проще: int (h, 16)
Кстати, источником вопроса является itunes persistent id - музыкальная библиотека xml-версия и версия iTunes hex
x = int(h,16)
if x > 0x7FFFFFFF:
x -= 0x100000000
import struct
Для Python 3 (с помощью комментариев):
h = '9DA92DAB'
struct.unpack('>i', bytes.fromhex(h))
Для Python 2:
h = '9DA92DAB'
struct.unpack('>i', h.decode('hex'))
или если это немного endian:
h = '9DA92DAB'
struct.unpack('<i', h.decode('hex'))
Здесь общая функция, которую вы можете использовать для hex любого размера:
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)
Это работает для 16-битных подписных int, вы можете расширить для 32-битных int. Он использует базовое определение 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)
Это очень поздний ответ, но вот функция, чтобы сделать выше. Это будет расширяться для любой длины, которую вы предоставляете. Поблагодарите за часть этого другого ответа SO (я потерял ссылку, поэтому, пожалуйста, предоставьте ее, если вы ее найдете).
def hex_to_signed(source):
"""Convert a string hex value to a signed hexidecimal value.
This assumes that source is the proper length, and the sign bit
is the first bit in the first byte of the correct length.
hex_to_signed("F") should return -1.
hex_to_signed("0F") should return 15.
"""
if not isinstance(source, str):
raise ValueError("string type required")
if 0 == len(source):
raise valueError("string is empty")
sign_bit_mask = 1 << (len(source)*4-1)
other_bits_mask = sign_bit_mask - 1
value = int(source, 16)
return -(value & sign_bit_mask) | (value & other_bits_mask)