在Python中将十六进制转换为双精度浮点数

4

Python: 将十六进制解包为双精度浮点数

这是值

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

我尝试了。
unpack('d', value)

但他需要一个字符串进行解包。现在它是一个列表。但当我将其更改为字符串时,长度将从8变为58。但双精度浮点数需要一个长度为8的值。

4个回答

12

使用''.join函数将列表转换为字符串:

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

7
请注意,将此转换为double有两种方法,取决于cpu是大端还是小端,因此最好明确指出您想要哪种方式。
>>> 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

仅为娱乐 - 这里是显式解码的方法

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

1
请在实施之前验证数值,并使用以下函数将十六进制转换为双精度或双精度转换为十六进制。
>>> import struct
>>> def double_to_hex(f):
    return hex(struct.unpack('<Q', struct.pack('<d', f))[0])

>>> def hex_to_double(f):
    return struct.unpack('!d', bytes.fromhex(f))[0]

>>> data = 12.982947
>>> hex_value = double_to_hex(data)
>>> print(hex_value)
0x4029f744d4456712
>>> double_value = hex_to_double(hex_value[2:])
>>> print(double_value)
12.982947

0

您还可以使用 ctypes 库进行此转换。

from ctypes import pointer, cast, POINTER, c_double, c_longlong

def convert_longlong_to_double(s):
    try:
        i = int(s, 10)                   # convert from hex to a Python int
    except Exception:
        i = s
    cp = pointer(c_longlong(i))           # make this into a c long long
    fp = cast(cp, POINTER(c_double))  # cast the long long pointer to a double pointer
    return fp.contents.value         # dereference the pointer, get the double

使用示例:

r1 = 0
r2 = 0
r3 = 16473
r4 = 0

longlong = (r1 << 16) | (r2 << 0) | (r3 << 48) | (r4 << 32)
print(convert_longlong_to_double(longlong))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接