Comment convertir la chaîne hexadécimale suivante en float (simple précision 32 bits) en Python?
"41973333" -> 1.88999996185302734375E1
"41995C29" -> 1.91700000762939453125E1
"470FC614" -> 3.6806078125E4
>>> 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
Mise à jour: voir le commentaire sur la façon de procéder dans Python 3.
Je recommande d'utiliser le module ctypes qui vous permet essentiellement de travailler avec des types de données de bas niveau. Dans votre cas, vous pourriez dire
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
Je pense que le module ctypes
est logique ici, car vous demandez essentiellement comment effectuer une conversion de bits de bas niveau. Votre question est essentiellement, comment dire à Python de prendre des données et d'interpréter ces données comme si ces mêmes bits exacts étaient d'un type de données différent?
En C, si vous aviez un int et vouliez interpréter ses bits comme un flottant, vous feriez à peu près la même chose, en prenant un pointeur puis en le castant et en le déréférençant:
int i = 0x41973333;
float f = *((float*)&i);
et c'est exactement ce que fait le code Python en utilisant la bibliothèque ctypes
dans mon exemple.
Je suppose que cette question concerne celle-ci et vous travaillez avec 4 octets plutôt que 8 chiffres hexadécimaux.
"\x41\x91\x33\x33"
est une chaîne de 4 octets même si elle ressemble à 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)
Si vous devez traiter la chaîne de chiffres hexadécimaux plutôt que les octets réels, vous pouvez utiliser struct.pack
pour le convertir, comme ceci
>>> for hx in ["41973333","41995C29","470FC614"]:
... print(struct.unpack(">f",struct.pack(">i",int(hx,16)))[0])
...
18.8999996185
19.1700000763
36806.078125
Découpez les chaînes hexadécimales en morceaux de 2 caractères (octets), faites de chaque morceau dans le bon octet avec le formatage int, struct.unpack lorsque vous avez terminé. C'est à dire.:
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]
émettant, comme souhaité:
18.8999996185 18.8999996185
19.1700000763 19.1700000763
36806.078125 36806.078125