plataforma de recopilación de tomar FPU modo de redondeo en cuenta en la impresión, las conversiones

StackOverflow https://stackoverflow.com/questions/2595563

Pregunta

EDIT: yo había cometido un error durante la sesión de depuración que me llevó a hacer esta pregunta. Las diferencias que estaba viendo eran, de hecho, en la impresión de una habitación doble y en analizar un doble (strtod). La respuesta de Stephen todavía cubre mi pregunta muy bien, incluso después de esta rectificación, así que creo que voy a dejar la cuestión solo en caso de que sea útil a alguien.

Algunos (la mayoría) de las plataformas C compilación que tengo acceso no tome la FPU modo de redondeo en cuenta cuando

  • convertir un entero de 64 bits a double;
  • imprimir un double.

Nada muy exótica aquí:. Mac OS X Leopard, varios Linuxes reciente y BSD variantes, Windows

Por otro lado, Mac OS X Snow Leopard parece tomar el modo de redondeo en cuenta al hacer estas dos cosas. Por supuesto, tener diferentes comportamientos me molesta no tener fin.

Estos son fragmentos típicos para los dos casos:

#if defined(__OpenBSD__) || defined(__NetBSD__) 
# include <ieeefp.h>
# define FE_UPWARD FP_RP
# define fesetround(RM) fpsetround(RM)
#else 
# include <fenv.h>
#endif

#include <float.h>
#include <math.h>

fesetround(FE_UPWARD);

...
double f;
long long b = 2000000001;
b = b*b;
f = b;

...
printf("%f\n", 0.1);

Mis preguntas son:

  1. ¿Hay algo que no fea que yo puedo hacer para normalizar el comportamiento en todas las plataformas? Algunos ocultos configurar para contar las plataformas que tienen el modo de redondeo en cuenta que no o viceversa?
  2. Es uno de los comportamientos estándar?
  3. ¿Qué estoy probable que encuentro cuando no se utiliza el modo de redondeo FPU? Ronda hacia cero? Redondeo al más cercano? Por favor, dime que no es sólo una alternativa:)

Con respecto a 2. Me pareció que el lugar en el estándar donde se dice que flota convierten en enteros son siempre truncado (redondeado hacia cero), pero no pudieron encontrar nada para el número entero -.> Dirección flotador

¿Fue útil?

Solución

Si no ha ajustado el modo de redondeo, que debería ser el modo por defecto de IEEE-754, que es todo el año a más cercano.

Para conversiones de número entero para flotar, el estándar C dice (§6.3.1.4):

  

Cuando un valor de tipo entero es   convertido a un tipo flotante real, si   el valor que se convierte puede ser   representada exactamente en el nuevo tipo,   Se mantiene sin cambios. Si el ser de valor   convertido es en el rango de valores   que se puede representar, pero no puede haber   representado exactamente, el resultado es   Los mayores o más cercana más cercana   disminuir valor representable, elegido en   de una manera definida por la implementación. si   el valor de ser convertido está fuera   el rango de valores que puede ser   representado, el comportamiento es   indefinido.

Así que ambos comportamientos se ajustan al estándar C.

dice El estándar C (§F.5) que las conversiones entre los formatos de punto flotante IEC60559 y secuencias de caracteres se redondearán correctamente según el estándar IEEE-754. Para los no-IEC60559 formatos, esto se recomienda, pero no es obligatorio. El estándar 1985 IEEE-754 dice (cláusula 5.4):

  

Conversiones se redondeará correctamente   como se especifica en la Sección 4 de operandos   se encuentra dentro de los intervalos especificados en   Tabla 3. De lo contrario, para el redondeo a   más cercano, el error en el convertida   resultados no deberá exceder en más de   0,47 unidades en el dígito menos significativo del destino del error que es   incurridos por el redondeo   especificaciones de la Sección 4, siempre   que el exponente más / desbordamiento no lo hace   ocurrir. En los modos de redondeo dirigida   el error tendrá el signo correcto   y no excederá de 1,47 unidades en el   el último lugar.

¿Qué sección (4) en realidad dice es que la operación se producirá de acuerdo con el modo de redondeo que prevalece. Es decir. si cambia el modo de redondeo, IEEE-754 dice que el resultado de Float-> conversión de cadenas debe cambiar en consecuencia. Lo mismo ocurre con Integer-> conversiones de flotación.

La revisión de la norma IEEE-754 2008 dice (cláusula 4.3):

  

La dirección de redondeo de atributo   afecta a todas las operaciones computacionales   que podría ser inexacta. numérica inexacta   resultados de punto flotante siempre tienen la   mismo signo que el resultado no redondeada.

Ambos conversiones se define para ser operaciones de cálculo en la cláusula 5, por lo que de nuevo que deben llevarse a cabo de acuerdo con el modo de redondeo que prevalece.

Yo diría que Snow Leopard tiene el comportamiento correcto en este caso (suponiendo que es correctamente redondeo de los resultados según el modo que prevalece redondeo). Si desea forzar el comportamiento de edad, siempre se puede envolver sus llamadas printf en el código que cambia el modo de redondeo, supongo, aunque eso no es claramente ideal.

Como alternativa, se podría utilizar el especificador de formato %a (coma flotante hexadecimal) en las plataformas compatibles C99. Puesto que el resultado de esta conversión es siempre exacto, nunca se efectuará mediante el modo de redondeo que prevalece. No creo que la biblioteca apoya %a de Windows C, pero que probablemente podría puerto de la implementación BSD o glibc con bastante facilidad si lo necesita.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top