Python中十六进制字符串转换为带符号整数

vecaoik1  于 2023-02-06  发布在  Python
关注(0)|答案(5)|浏览(386)

如何在Python 3中将十六进制字符串转换为带符号的int型?
我能想到的最好办法就是

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

有更简单的方法吗?无符号更简单:整数(小时,16)
顺便说一句,问题的起源是itunes persistent id - music library xml version and iTunes hex version

bmp9r5qi

bmp9r5qi1#

在n位二进制补码中,位具有值:
位0 = 20
位1 = 21
位n-2 = 2n-2
位n-1 = -2n-1
但是位n-1在无符号时的值为2n-1,因此数字2n太大。如果位n-1被设置,则减去2n:

def twos_complement(hexstr, bits):
    value = int(hexstr, 16)
    if value & (1 << (bits - 1)):
        value -= 1 << bits
    return value

print(twos_complement('FFFE', 16))
print(twos_complement('7FFF', 16))
print(twos_complement('7F', 8))
print(twos_complement('FF', 8))

输出:

-2
32767
127
-1
sxpgvts3

sxpgvts32#

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'))
pxq42qpu

pxq42qpu3#

下面是一个通用函数,可用于任意大小的十六进制:

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)
mrfwxfqh

mrfwxfqh4#

这适用于16位有符号整型数,你可以扩展到32位整型数。它使用了2的补码有符号数的基本定义。还要注意,与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)
ttp71kqs

ttp71kqs5#

这是一个很晚的答案,但这里有一个函数来做以上。这将扩展到任何长度,你提供。信贷的一部分,这是另一个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)

相关问题