Empaquetando y desempaquetando flotador binario en python

Estoy teniendo algunos problemas con el empaquetado y desempaquetado de flotadores binarios en python al hacer una escritura de archivo binario. Esto es lo que he hecho:

import struct f = open('file.bin', 'wb') value = 1.23456 data = struct.pack('f',value) f.write(data) f.close() f = open('file.bin', 'rb') print struct.unpack('f',f.read(4)) f.close() 

El resultado que obtengo es el siguiente:

 (1.2345600128173828,) 

¿Qué está pasando con los dígitos extra? ¿Es este un error de redondeo? ¿Como funciona esto?

En la mayoría de las plataformas, los flotadores de Python son lo que C llamaría un double , pero en cambio escribiste tus datos como float , que tiene la mitad de la precisión.

Si usara el double , tendría menos pérdida de precisión:

 >>> data = struct.pack('d',value) >>> struct.unpack('d',data) (1.23456,) >>> data = struct.pack('f',value) >>> struct.unpack('f',data) (1.2345600128173828,) 

El formato de estructura float ofrece solo una precisión (24 bits para la precisión significativa) .

Es un problema decimal a binario.

¿Sabes cómo se repiten algunas fracciones en decimal? Por ejemplo, 1/3 es 0.3333333-> para siempre. 1/7 es 0.142857142857 [142857] -> para siempre.

Así que aquí está el truco: las fracciones que se repiten son aquellas con un denominador que tiene un factor que no es un factor de 10, por ejemplo, no un múltiplo de 2 y / o 5.

  • 1/2 divisiones uniformemente
  • 1/3 repeticiones
  • 1/4 se divide uniformemente
  • 1/5 se divide uniformemente
  • 1/6 repeticiones
  • 1/7 repeticiones
  • 1/8 se divide uniformemente
  • 1/9 repeticiones
  • 1/10 se divide uniformemente
  • 1/11 repeticiones
  • Etcétera

Entonces, ¿cómo funciona eso en binario? Bueno, un poco apesta, porque el único factor que se divide uniformemente es 2. Todos los demás números primos, además de 2, tendrán decimales repetitivos que se repetirán para siempre, y eso incluye décimas, centésimas, etc., que tienen un factor de 5 en el denominador . 1.2345 es 12345/10000, que tiene los factores 2 y 5 en el denominador, y que 5 significa que tienes un decimal repetido en binario que se repite para siempre.

Pero no puedes repetir para siempre. Lo que significa que tendrá que redondear el decimal para que quepa en los dígitos binarios que codifican su flotador.

Cuando se convierte de nuevo a decimal, se revela el error de redondeo.

El resultado final de la encoding es: calcule las divisiones lo más tarde posible para evitar que estos errores se acumulen con cada cálculo.