2010-03-19 13 views
5

Necesito representar un número de coma flotante doble IEEE 754-1985 (64 bits) en una forma textual legible por el ser humano, con la condición de que la forma textual pueda ser analizada de nuevo en exactamente el mismo número (bit-wise).Representación textual exacta de un "doble" IEEE

¿Es esto posible/práctico sin solo imprimir los bytes sin formato? En caso afirmativo, el código para hacer esto sería muy apreciado.

+1

Idioma importa. ¿En qué idioma estás trabajando? Es casi imposible proporcionar código sin un lenguaje específico mencionado en el problema. –

+0

No mencioné el idioma (D) porque es comparablemente raro, así que estaba planeando reescribir un algoritmo escrito en cualquier idioma para D. –

+0

¿Qué tal NaN, -0.0, inf, -inf? La respuesta actual no parece tener esto en cuenta. –

Respuesta

11

La mejor opción: utilizar el formato hexadecimal C99 de punto flotante:

printf("%a", someDouble); 

Cuerdas producidos de esta manera se puede convertir de nuevo en double con la función C99 strtod(), y también con las funciones scanf(). Varios otros idiomas también admiten este formato. Algunos ejemplos:

decimal number %a format  meaning 
-------------------------------------------- 
2.0    0x1.0p1  1.0 * 2^1 
0.75    0x1.8p-1  1.5 * 2^-1 

El formato hexadecimal tiene la ventaja de que todas las representaciones son exacta. Por lo tanto, convertir la cadena nuevamente en punto flotante siempre dará el número original, incluso si alguien cambia el modo de redondeo en el que se realiza la conversión. Esto no es cierto para formatos inexactos.

Si no quiere utilizar el formato hexadecimal por cualquier razón, y está dispuesto a suponer que el modo de redondeo siempre será redondo al más cercano (el predeterminado), entonces puede salirse con la formatación de sus datos como decimales con al menos 17 dígitos significativos. Si tiene una rutina de conversión correctamente redondeada (la mayoría de las plataformas no lo hacen), esto le garantizará que puede hacer un viaje de ida y vuelta desde doble a cadena y hacia atrás sin pérdida de precisión.

+0

¡Gracias por la respuesta detallada! –

1

Sí, se puede hacer, aunque la implementación depende del idioma. La idea básica es simplemente imprimirla con suficiente precisión.

Tenga en cuenta que el reverso es no cierto: algunos números que se pueden representar con precisión en decimal simplemente no se pueden representar en binario.

2

El marco .NET tiene un formato de ida y vuelta para esto:

string formatted = myDouble.ToString("r"); 

De la documentación:

Los de ida y vuelta especificador garantiza que un valor numérico convierte en una cadena se analizará de nuevo en el mismo valor numérico . Cuando un valor numérico es formateado con este especificador, es probado por primera vez utilizando el formato general, con 15 espacios de precisión para un doble y 7 espacios de precisión para un individual. Si el valor es analizado correctamente al mismo valor numérico, se formatea utilizando el especificador de formato general . Sin embargo, si el valor no se analiza correctamente con el mismo valor numérico, entonces el valor se formatea con 17 dígitos de precisión para una precisión de 0 y 2 dígitos de para una sola.

Este método podría, por supuesto, ser recreado en casi cualquier idioma.

5

sonido como si quieres Burger's algorithm (PDF):

En el modo de formato libre el algoritmo genera la cadena de salida correctamente redondeada más corta que convierte a el mismo número cuando se lee de nuevo en independientemente de cómo el el lector rompe los lazos al redondear.

Sample source code (en C y esquema) también está disponible.

Este es el algoritmo utilizado en Python 3.x para garantizar que float s se pueden convertir a cadenas y a la espalda sin pérdida de precisión. En Python 2.x, float s eran siempre representados con 17 dígitos significativos porque:

repr(float) produce 17 dígitos significativos porque resulta que eso es suficiente (en la mayoría de las máquinas) para que eval(repr(x)) == x exactamente para todos los flotadores finitos x, pero redondear a 16 dígitos no es suficiente para que sea cierto. (Origen: http://docs.python.org/tutorial/floatingpoint.html)

Cuestiones relacionadas