pythonpython-3.xintegerhex

Hex string to signed int in Python


How do I convert a hex string to a signed int in Python 3?

The best I can come up with is

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

Is there a simpler way? Unsigned is so much easier: int(h, 16)

BTW, the origin of the question is itunes persistent id - music library xml version and iTunes hex version


Solution

  • In n-bit two's complement, bits have value:

    bit 0 = 20
    bit 1 = 21
    bit n-2 = 2n-2
    bit n-1 = -2n-1

    But bit n-1 has value 2n-1 when unsigned, so the number is 2n too high. Subtract 2n if bit n-1 is set:

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

    Output:

    -2
    32767
    127
    -1