Cómo convertir la siguiente cadena hexadecimal a float (precisión simple de 32 bits) en Python?Convertir hex a flotante
"41973333" -> 1.88999996185302734375E1
"41995C29" -> 1.91700000762939453125E1
"470FC614" -> 3.6806078125E4
Cómo convertir la siguiente cadena hexadecimal a float (precisión simple de 32 bits) en Python?Convertir hex a flotante
"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
Actualización: véase el comentario sobre la manera de hacer esto en Python 3.
supongo esta pregunta se refiere a this one y se trabaja con 4 bytes en lugar de 8 dígitos hexadecimales.
"\x41\x91\x33\x33"
es una cadena de 4 bytes a pesar de que parece que 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 es necesario para hacer frente a la cadena de hexdigits en lugar de los bytes reales, puede utilizar struct.pack
para convertirlo, como este
>>> for hx in ["41973333","41995C29","470FC614"]:
... print(struct.unpack(">f",struct.pack(">i",int(hx,16)))[0])
...
18.8999996185
19.1700000763
36806.078125
recomiendo el uso de the ctypes module que básicamente le permite trabajar con tipos de datos de bajo nivel. En su caso se podría decir
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
Creo que el módulo ctypes
tiene sentido aquí, porque básicamente estás preguntando cómo realizar la fundición bits de bajo nivel. Su pregunta es, básicamente, ¿cómo le digo a Python que tome algunos datos e interprete esos datos como si esos mismos bits exactos fueran un tipo de datos diferente?
En C si tuviera un int y quería interpretar sus bits como un flotador, que haría más o menos lo mismo, teniendo un puntero y luego fundición y derreferenciándolo:
int i = 0x41973333;
float f = *((float*)&i);
y eso es exactamente lo que el código de Python que usa la biblioteca ctypes
está haciendo en mi ejemplo.
Cortar las cadenas hexagonales en trozos de 2 caracteres (bytes), convertir cada fragmento en el byte derecho con formato int, struct.unpack cuando haya terminado. Es decir:
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]
emisor, según se desee:
18.8999996185 18.8999996185
19.1700000763 19.1700000763
36806.078125 36806.078125
Gentelmen ... He aquí:
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
perdón por el pequeño ".value" en t él termina ...
este código ha sido usado como clase en mi programa por casi 2 años.
(con un poco de edición, puede convertirlo fácilmente en una función)
crédito a PyTony en DaniWeb para el código.
a diferencia de la computación no dinámico,
el código no está cableada duro para un tamaño fijo flotador,
y funciona con cualquier bytes de tamaño.
aunque creo que todavía tenemos algunos errores que resolver.XDD
(Voy a editar el código más tarde (si puedo) con la actualización)
todo es bueno, aunque por el momento, aunque ...
havn't I tenían un problema de convertir los modelos de juegos 3D con él. :)
Vaya, ese código es impenetrable ... – SamB
El enfoque de ctypes no funciona cuando la cadena hexadecimal contiene los ceros a la izquierda. No lo uses
En python3 tiene que usar 'bytes.fromhex ('41973333')' en lugar de ''41973333'.decode (' hex ')' –