views:

49

answers:

2

Python: Unpack from hex to double

This is the value

value = ['\x7f', '\x15', '\xb7', '\xdb', '5', '\x03', '\xc0', '@']

I tried

unpack('d', value)

but he needs a string for unpacking. It is a list now. But when I change it to a string, the length will change from 8 to 58. But a double needs a value of the length 8.

+5  A: 

Use ''.join join to convert the list to a string:

>>> value = ['\x7f', '\x15', '\xb7', '\xdb', '5', '\x03', '\xc0', '@']
>>> ''.join(value)
'\x7f\x15\xb7\xdb5\x03\xc0@'
>>> from struct import unpack
>>> unpack('d', ''.join(value))
(8198.4207676749193,)
Mark Byers
+2  A: 

Note that there are two ways to convert this to a double, depending on whether the cpu is bigendian oe littleendian, so it's best to be explicit about which one you want

>>> from struct import unpack
>>> value = ['\x7f', '\x15', '\xb7', '\xdb', '5', '\x03', '\xc0', '@']
>>> unpack('<d', ''.join(value))[0]
8198.42076767492
>>> unpack('>d', ''.join(value))[0]
1.4893584640656973e+304

and just for fun - here's how to decode the double explicitly

>>> value = ['\x7f', '\x15', '\xb7', '\xdb', '5', '\x03', '\xc0', '@']
>>> bytes = map(ord,reversed(value))
>>> sign = (1,-1)[bytes[0]>>7]
>>> exp = ((0x7f&bytes[0])<<4) + (bytes[1]>>4) - 1023
>>> mantissa = reduce(lambda x,y: (x<<8) + y, bytes[2:], bytes[1]&0xf)
>>> sign*2**exp*(1+mantissa*2**-52)
8198.4207676749193
gnibbler