How to convert the following hex string to float (single precision 32-bit) in Python?
"41973333" -> 1.88999996185302734375E1"41995C29" -> 1.91700000762939453125E1"470FC614" -> 3.6806078125E4
Best Answer
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
Converting a hexadecimal string to a float in Python can be done using the built-in float()
function along with the int()
function. This is a useful skill to have when dealing with hexadecimal data, especially in fields like cryptography or low-level programming.
Here's how you can convert a hexadecimal string to a float in Python:
- First, you need to use the
int()
function to convert the hexadecimal string to an integer. - Then, you can use the
float()
function to convert the integer to a float. - Finally, you'll have the hexadecimal string converted to a float.
Let's see an example:
hex_string = '3f800000'integer = int(hex_string, 16)float_number = float(integer)print(float_number)
In this example, we have a hexadecimal string '3f800000'. We convert it to an integer using the int()
function with base 16 (hexadecimal). Then, we convert the integer to a float using the float()
function. Finally, we print the resulting float number.
The output of the above code will be:
1.0
As you can see, the hexadecimal string '3f800000' is converted to a float value of 1.0.
It's important to note that the hexadecimal string must represent a valid float value. Otherwise, you may get unexpected results or errors.
Now you know how to convert a hexadecimal string to a float in Python. This can be a handy skill when working with hexadecimal data. Experiment with different hexadecimal strings and explore further possibilities!
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 intcp = pointer(c_int(i)) # make this into a c integerfp = cast(cp, POINTER(c_float)) # cast the int pointer to a float pointerreturn fp.contents.value # dereference the pointer, get the floatprint convert("41973333") # returns 1.88999996185302734375E1print convert("41995C29") # returns 1.91700000762939453125E1print 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.
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.899999618519.170000076336806.078125
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.899999618519.1700000763 19.170000076336806.078125 36806.078125
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)
Gentelmen... Behold:
class fl:def __init__(this, value=0, byte_size=4):this.value = valueif 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 FMelse: this.value = 0.0print fl( 0x41973333 ).value # >>> 18.899999618530273print fl( 0x41995C29 ).value # >>> 19.170000076293945print fl( 0x470FC614 ).value # >>> 36806.078125print 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
sorry for the little ".value" at the end...
this code has been used as a class in my program for nearly 2 years now.
(with a little editing, you can easily make it into a function)
credit to PyTony over at DaniWeb for the code.
unlike non-dynamic computing,
the code is not hard-wired to a fixed float size,
and works with any byte-size.
though I guess we still have a few bugs to work out. XDD
(I'll edit this code later (if I can) with the update)
all is good though for now though...
I havn't had a problem converting 3D game models with it. :)