plataforma de recopilación de tomar FPU modo de redondeo en cuenta en la impresión, las conversiones
-
25-09-2019 - |
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:
- ¿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?
- Es uno de los comportamientos estándar?
- ¿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
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.