48 Stimmen

Hex in Float umwandeln

Wie konvertiert man die folgende Hex-Zeichenkette in Python in Float (einfache Genauigkeit 32-Bit)?

"41973333" -> 1.88999996185302734375E1

"41995C29" -> 1.91700000762939453125E1

"470FC614" -> 3.6806078125E4

81voto

Denis Otkidach Punkte 30334

En 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

En 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

24voto

Eli Courtwright Punkte 174547

Ich empfehle die Verwendung von das Modul ctypes mit dem Sie im Grunde genommen mit Datentypen auf niedriger Ebene arbeiten können. In Ihrem Fall könnten Sie sagen

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

Ich glaube, dass die ctypes Modul ist hier sinnvoll, weil Sie im Wesentlichen fragen, wie man Low-Level-Bit-Casting durchführen kann. Ihre Frage ist im Grunde, wie ich Python anweisen kann, einige Daten zu nehmen und diese Daten so zu interpretieren, als ob genau dieselben Bits einen anderen Datentyp hätten.

In C würde man, wenn man einen int hätte und seine Bits als Float interpretieren wollte, in etwa das Gleiche tun, indem man einen Zeiger nimmt und ihn dann castet und dereferenziert:

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

und das ist genau das, was der Python-Code, der die ctypes Bibliothek in meinem Beispiel tut.

6voto

John La Rooy Punkte 278961

Ich nehme an, diese Frage bezieht sich auf éste und Sie arbeiten mit 4 Bytes statt mit 8 Hexadezimalziffern.

"\x41\x91\x33\x33" ist eine 4-Byte-Zeichenkette, auch wenn sie wie 16 aussieht

>>> 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)

Wenn Sie nicht die eigentlichen Bytes, sondern die Hexadezimalzeichenfolge benötigen, können Sie struct.pack um sie umzuwandeln, etwa so

>>> for hx in ["41973333","41995C29","470FC614"]:
...     print(struct.unpack(">f",struct.pack(">i",int(hx,16)))[0])
... 
18.8999996185
19.1700000763
36806.078125

4voto

Alex Martelli Punkte 805329

Zerlegen Sie die Hex-Zeichenketten in 2-Zeichen-Stücke (Bytes), machen Sie aus jedem Stück das richtige Byte mit Int-Formatierung, struct.unpack, wenn Sie fertig sind. D.h.:

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]

emittieren, wie gewünscht:

18.8999996185 18.8999996185
19.1700000763 19.1700000763
36806.078125 36806.078125

1voto

joseppinilla Punkte 86

Wenn Sie von einer Zeichenkette ausgehen und die Werte nicht aufteilen oder indizieren müssen.

import struct
...
q = int('0x425c0000',16)
b8 = struct.pack('i', q)
dec, = struct.unpack('f', b8)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X