Convert hex to float
Solution 1
In 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
In 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
Solution 2
I recommend using the ctypes module which basically lets you work with low level data types. In your case you could say
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
I believe that the ctypes
module makes sense here, because you're essentially asking how to perform low-level bit casting. Your question is basically, how do I tell Python to take some data and interpret that data as if those exact same bits were a different data type?
In C if you had an int and wanted to interpret its bits as a float, you'd do roughly the same thing, taking a pointer and then casting and dereferencing it:
int i = 0x41973333;
float f = *((float*)&i);
and that's exactly what the Python code using the ctypes
library is doing in my example.
Solution 3
I'm guessing this question relates to this one and you are working with 4 bytes rather than 8 hex digits.
"\x41\x91\x33\x33"
is a 4 byte string even though it looks like 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)
If you do need to deal with the string of hexdigits rather than the actual bytes, you can use struct.pack
to convert it, like this
>>> for hx in ["41973333","41995C29","470FC614"]:
... print(struct.unpack(">f",struct.pack(">i",int(hx,16)))[0])
...
18.8999996185
19.1700000763
36806.078125
Solution 4
Slice up the hex strings into 2-character chunks (bytes), make each chunk into the right byte with int formatting, struct.unpack when done. I.e.:
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]
emitting, as desired:
18.8999996185 18.8999996185
19.1700000763 19.1700000763
36806.078125 36806.078125
Solution 5
When working from string and without having to slice or index values.
import struct
...
q = int('0x425c0000',16)
b8 = struct.pack('i', q)
dec, = struct.unpack('f', b8)
Related videos on Youtube
Blemone
Updated on April 04, 2021Comments
-
Blemone about 3 years
How to convert the following hex string to float (single precision 32-bit) in Python?
"41973333" -> 1.88999996185302734375E1 "41995C29" -> 1.91700000762939453125E1 "470FC614" -> 3.6806078125E4
-
John La Rooy over 14 yearsIn python3 you have to use
bytes.fromhex('41973333')
instead of'41973333'.decode('hex')
-
Varadaraju G about 3 years
print(struct.unpack('!f', bytes.fromhex('D'))[0])
ValueError: non-hexadecimal number found in fromhex() arg at position 1 any reason? -
Denis Otkidach about 3 years@VaradarajuG
'D'
is at position 0, and position 1 points to the end of string. Each hexadecimal encoded byte consist of 2 chars, so the length of your string must be even. Did you meanbytes.fromhex('0D')
-
Benyamin Jafari - aGn almost 3 years
struct.unpack('!f', bytes.fromhex('9f780441ccb646'))[0]
Out:error: unpack requires a buffer of 4 bytes
-
Vandan Revanur almost 2 years@BenyaminJafari The buffer’s size in bytes must match the size required by the format. So for your hex string, there are 7 bytes, which could be interpreted for example as a set of float, int and char. So if you do :
struct.unpack('!fhc', bytes.fromhex('9f780441ccb646'))[0]
, here f corresponds to float, h corresponds to int, and c corresponds to char. Then the output will be :-5.251956147854424e-20
-
Vandan Revanur almost 2 yearsI used your method to convert a hex string to float and it returns a wrong value.
convert('9f91dd57' )
I get the output as :-6.177606473100781e-20
However, when I use :float.fromhex('9f91dd57')
, I get the right answer:2677136727.0
. Could you please say why this is happening?