将十六进制转换为浮点数

48 投票
6 回答
102446 浏览
提问于 2025-04-15 15:12

如何在Python中将以下十六进制字符串转换为浮点数(单精度32位)?

"41973333" -> 1.88999996185302734375E1

"41995C29" -> 1.91700000762939453125E1

"470FC614" -> 3.6806078125E4

6 个回答

6

我猜这个问题和这个问题有关,你可能是在处理4个字节,而不是8个十六进制数字。

"\x41\x91\x33\x33"是一个4字节的字符串,尽管它看起来像是16个字符。

>>> len("\x41\x91\x33\x33")
4
>>> import struct  
>>> struct.unpack(">fff","\x41\x97\x33\x33\x41\x99\x5C\x29\x47\x0F\xC6\x14")
(18.899999618530273, 19.170000076293945, 36806.078125)

如果你需要处理的是十六进制数字的字符串,而不是实际的字节,你可以使用struct.pack来进行转换,像这样:

>>> for hx in ["41973333","41995C29","470FC614"]:
...     print(struct.unpack(">f",struct.pack(">i",int(hx,16)))[0])
... 
18.8999996185
19.1700000763
36806.078125
24

我推荐使用ctypes模块,这个模块基本上可以让你处理一些底层的数据类型。在你的情况下,你可以这样说:

from ctypes import *

def convert(s):
    i = int(s, 16)                   # convert from hex to a Python int
    cp = pointer(c_int(i))           # make this into a c integer
    fp = cast(cp, POINTER(c_float))  # cast the int pointer to a float pointer
    return fp.contents.value         # dereference the pointer, get the float

print convert("41973333")    # returns 1.88999996185302734375E1

print convert("41995C29")    # returns 1.91700000762939453125E1

print convert("470FC614")    # returns 3.6806078125E4

我觉得ctypes模块在这里很合适,因为你实际上是在问如何进行低级的位转换。你的问题基本上是,怎么告诉Python把一些数据当成另一种数据类型来理解,尽管这些数据的位是一样的?

在C语言中,如果你有一个整数(int),想把它的位当成浮点数(float)来理解,你大概会做类似的事情,先获取一个指针,然后进行转换和解引用:

int i = 0x41973333;
float f = *((float*)&i);

而这正是我示例中使用ctypes库的Python代码所做的事情。

83

Python 3中:

>>> import struct
>>> struct.unpack('!f', bytes.fromhex('41973333'))[0]
18.899999618530273
>>> struct.unpack('!f', bytes.fromhex('41995C29'))[0]
19.170000076293945
>>> struct.unpack('!f', bytes.fromhex('470FC614'))[0]
36806.078125

Python 2中:

>>> import struct
>>> struct.unpack('!f', '41973333'.decode('hex'))[0]
18.899999618530273
>>> struct.unpack('!f', '41995C29'.decode('hex'))[0]
19.170000076293945
>>> struct.unpack('!f', '470FC614'.decode('hex'))[0]
36806.078125

撰写回答