hexa python binary floating-point hex decimal

hexa to binary python



Convertir hexadecimal a flotar (6)

¿Cómo convertir la siguiente cadena hexadecimal a flotar (precisión única de 32 bits) en Python?

"41973333" -> 1.88999996185302734375E1 "41995C29" -> 1.91700000762939453125E1 "470FC614" -> 3.6806078125E4


Corte las cadenas hexadecimales en trozos de 2 caracteres (bytes), convierta cada trozo en el byte derecho con el 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]

emitiendo, según se desee:

18.8999996185 18.8999996185 19.1700000763 19.1700000763 36806.078125 36806.078125


El enfoque de ctypes no funciona cuando la cadena hexadecimal contiene ceros iniciales. No lo uses


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

lo siento por el pequeño ".valor" al final ...
este código ha sido utilizado como una clase en mi programa durante casi 2 años.
(Con un poco de edición, puedes convertirlo fácilmente en una función)

crédito a PyTony en DaniWeb por el código.

a diferencia de la computación no dinámica,
el código no está cableado a un tamaño flotante fijo,
y funciona con cualquier tamaño de byte.

aunque supongo que todavía tenemos algunos errores que resolver. XDD
(Editaré este código más tarde (si puedo) con la actualización)

todo está bien aunque por ahora aunque ...
No he tenido problemas para convertir modelos de juegos en 3D con él. :)


Recomiendo usar el módulo ctypes que básicamente le permite trabajar con tipos de datos de bajo nivel. En tu caso podrías 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 conversión de 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 fueran exactamente un tipo de datos diferente?

En C si tuvieras un int y quisieras interpretar sus bits como un flotador, harías más o menos lo mismo, tomando un puntero y luego lanzándolo y desreferiéndolo:

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

y eso es exactamente lo que hace el código Python que usa la biblioteca ctypes en mi ejemplo.


Supongo que esta pregunta se relaciona con esta y usted está trabajando con 4 bytes en lugar de 8 dígitos hexadecimales.

"/x41/x91/x33/x33" es una cadena de 4 bytes, aunque se parece a 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 necesitas lidiar con la cadena de hexdigits en lugar de los bytes reales, puedes usar 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


>>> 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: ver comentario sobre cómo hacer esto en Python 3.