十六进制转换浮动(Convert hex to float)

2019-08-21 05:41发布

如何转换以下的十六进制字符串浮动(单精度32位)在Python?

"41973333" -> 1.88999996185302734375E1

"41995C29" -> 1.91700000762939453125E1

"470FC614" -> 3.6806078125E4

Answer 1:

>>> 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评论。



Answer 2:

我建议使用的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,想解释其位作为浮动,你会做大致相同的事情,采用指针,然后铸造和取消引用它:

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

而这正是使用了Python代码ctypes图书馆在我的例子在做什么。



Answer 3:

我猜这个问题涉及到这一块 ,你用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)

如果你需要处理hexdigits而不是实际的字节串,就可以使用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


Answer 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


Answer 5:

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年。
(一点点的编辑,你可以很容易地使之成为一个功能)

信贷在DaniWeb PyTony过的代码。

不像非动态计算,
代码没有硬连线到固定浮子大小,
与任何字节大小的作品。

但我想我们还是有一些缺陷,以锻炼身体。 XDD
(我会更新以后编辑代码(如果我能))

一切都很好,虽然现在虽然...
我没有带过一个问题转换3D游戏的机型吧。 :)



Answer 6:

当十六进制字符串中包含前导零的ctypes的方法是行不通的。 不要使用它。



文章来源: Convert hex to float