如何在Python中将以下十六进制字符串转换为float(单精度32位)?
"41973333" -> 1.88999996185302734375E1
"41995C29" -> 1.91700000762939453125E1
"470FC614" -> 3.6806078125E4
答案 0 :(得分:51)
>>> 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
更新:请参阅有关如何在Python 3中执行此操作的注释。
答案 1 :(得分:12)
我建议使用the ctypes module,它基本上允许您使用低级数据类型。在你的情况下,你可以说
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并想把它的位解释为一个浮点数,那你就做了大致相同的事情,拿一个指针然后转换并取消引用它:
int i = 0x41973333;
float f = *((float*)&i);
这正是使用ctypes
库的Python代码在我的示例中所做的。
答案 2 :(得分:5)
我猜这个问题与this one有关,而你正在使用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
答案 3 :(得分:4)
将十六进制字符串分成2个字符的块(字节),使用int格式化每个块进入正确的字节,完成时使用struct.unpack。即:
import struct
testcases = {
"41973333": 1.88999996185302734375E1,
"41995C29": 1.91700000762939453125E1,
"470FC614": 3.6806078125E4,
}
def hex2float(s):
bins = ''.join(chr(int(s[x:x+2], 16)) for x in range(0, len(s), 2))
return struct.unpack('>f', bins)[0]
for s in testcases:
print hex2float(s), testcases[s]
根据需要发光:
18.8999996185 18.8999996185
19.1700000763 19.1700000763
36806.078125 36806.078125
答案 4 :(得分:1)
当处理字符串且无需切片或索引值时。
string freq
78 huck 4
63 wood 4
77 chuc 4
132 chuck 4
8 ood 4
7 woo 4
21 chu 4
23 uck 4
22 huc 4
20 dch 3
答案 5 :(得分:0)
Gentelmen ......看哪:
class fl:
def __init__(this, value=0, byte_size=4):
this.value = value
if this.value: # speedy check (before performing any calculations)
Fe=((byte_size*8)-1)//(byte_size+1)+(byte_size>2)*byte_size//2+(byte_size==3)
Fm,Fb,Fie=(((byte_size*8)-(1+Fe)), ~(~0<<Fe-1), (1<<Fe)-1)
FS,FE,FM=((this.value>>((byte_size*8)-1))&1,(this.value>>Fm)&Fie,this.value&~(~0 << Fm))
if FE == Fie: this.value=(float('NaN') if FM!=0 else (float('+inf') if FS else float('-inf')))
else: this.value=((pow(-1,FS)*(2**(FE-Fb-Fm)*((1<<Fm)+FM))) if FE else pow(-1,FS)*(2**(1-Fb-Fm)*FM))
del Fe; del Fm; del Fb; del Fie; del FS; del FE; del FM
else: this.value = 0.0
print fl( 0x41973333 ).value # >>> 18.899999618530273
print fl( 0x41995C29 ).value # >>> 19.170000076293945
print fl( 0x470FC614 ).value # >>> 36806.078125
print fl( 0x00800000 ).value # >>> 1.1754943508222875e-38 (minimum float value)
print fl( 0x7F7FFFFF ).value # >>> 340282346638528859811704183484516925440L (maximum float value)
# looks like I've found a small bug o.o
# the code still works though (the numbers are properly formatted)
# the result SHOULD be: 3.4028234663852886e+38 (rounded)
print fl( 0x3f80000000, 5 ).value # >>> 1.0
对不起最后的小“.value”...... 这个代码已经在我的程序中用作了近2年的课程 (通过一点编辑,你可以很容易地将它变成一个函数)
感谢PyTony在DaniWeb上获取代码。
与非动态计算不同,
代码没有硬连线到固定的浮动尺寸,
并适用于任何字节大小。
虽然我猜我们还有一些问题要解决。 XDD
(我稍后会编辑此代码(如果可以的话)更新)
答案 6 :(得分:-1)
当十六进制字符串包含前导零时,ctypes方法不起作用。不要使用它。