Foros del Web » Programación para mayores de 30 ;) » C/C++ »

Números Subnormales en C (estándar C99 y GCC 4.7)

Estas en el tema de Números Subnormales en C (estándar C99 y GCC 4.7) en el foro de C/C++ en Foros del Web. Buenas. Estoy estudiando en detalle el estándar C99 del lenguaje C. En particular el tema de los tipos de punto flotante. Tengo un problema relativo ...
  #1 (permalink)  
Antiguo 28/01/2013, 14:53
 
Fecha de Ingreso: junio-2005
Ubicación: Argentina
Mensajes: 90
Antigüedad: 18 años, 11 meses
Puntos: 2
Números Subnormales en C (estándar C99 y GCC 4.7)

Buenas.

Estoy estudiando en detalle el estándar C99 del lenguaje C.
En particular el tema de los tipos de punto flotante.

Tengo un problema relativo a las macros de math.h que clasifican valores de punto flotante.
Obtengo resultados "erróneos" (o eso parece) cuando analizo valores subnormales.
Detalles:

El estándar C99 menciona al estándar de números en punto flotante ISO/IEC/IEEE 60559 (también conocido como IEEE 754, para base binaria).

Me interesan las macros que clasifican los valores que puede tomar una constante de punto flotante, con o sin la normativa IEEE 754.

En la librería math.h se encuentra, por ejemplo, la macro

int fpclassify(x)

Da un valor "FP_SUBNORMAL" (valor int definido en math.h) si el parámetro x es un número finito subnormal, en el tipo que fuere.

Según lo que interpreto del estándar C99,
la macro fpclassify() detecta primero el tipo al que pertenece x, digamos float, double o long double.
Luego "se fija" si x es un valor subnormal, en "ese" tipo, y sólo en ese caso devuelve el valor FP_SUBNORMAL.

Ahora bien.
Si yo escribo, por ejemplo:

fpclassify(FLT_MIN / 4.0f)

estoy generando un número subnormal de tipo float,
ya que FLT_MIN es el mínimo punto flotante positivo normal, de tipo float.
Al dividirlo por 4.0f, obtengo de nuevo un valor de punto flotante, que está debajo de ese mínimo, y que todavía es de tipo float.


Si el sistema no soportara valores subnormales, obtendría automáticamente el valor 0.0f como resultado.
Ahora bien, mi compilador, el GCC 4.7.1, con las opciones -std=c99 (y/o -pedantic), no me genera un 0.0f,
sino que da un valor subnormal de tipo float.

Sin embargo, cuando le aplico la macro fpclassify, el resultado que me da es FP_NORMAL, cuando lo esperado era FP_SUBNORMAL, ya que el número es subnormal.

Esta "anomalía" también se produce con double.
En cambio con long double, me da el resultado correcto: FP_SUBNORMAL.

¿Es esto posible? ¿O el compilador GCC tiene un bug en esto?
Otro detalle importante:

La macro FLT_EVAL_METHOD de float.h me da a mí el valor 2.
(Esto quiere decir que el resultado de todos los cálculos se llevan automáticamente a long double).

Mi duda es esta: ¿el estándar C99 condiciona, a través de FLT_EVAL_METHOD, la manera en que se evalúa la macro fpclassify? ¿O es esto una interpretación errónea que hace el compilador GCC? ¿O es un bug?
¿Los valores que me devuelve fpclassify con el compilador GCC 4.7.1 se consideran "los correctos", desde el punto de vista teórico del estándar C99?

Mi impresión es que el comportamiento de fpclassify es equivocado.

Saludos y gracias
  #2 (permalink)  
Antiguo 04/02/2013, 03:39
 
Fecha de Ingreso: junio-2010
Ubicación: Madrid
Mensajes: 620
Antigüedad: 13 años, 11 meses
Puntos: 73
Respuesta: Números Subnormales en C (estándar C99 y GCC 4.7)

Aunque no conozco en detalle el estándar C99, supongo que se debe a cómo se efectúan los cálculos en coma flotante.

El procesador de coma flotante utiliza internamente un tipo de 80 bits para prevenir los posibles overflow/underflow en los cálculos con tipos float y double. Este tipo de 80 bits (10 bytes) es accesible como long double, el tamaño que te indicará el operador sizeof probablemente será, por cuestiones de direccionamiento, de 12 bytes en sistemas de 32 bits (aunque sólo se utilicen 10) y de 16 en sistemas de 64 bits. Ojo, porque hay compiladores en los que el tipo long double es sinónimo de double (creo que Visual C es uno de ellos).

Supongo que lo que ocurre es que, dado que hay promoción a long double, el valor FP_SUBNORMAL te lo devolverá cuando el resultado de tu operación vaya a ser un valor subnormal... para long double.

Prueba a ver qué pasa definiendo esa macro como 0 (no se promociona) ó 1 (float promociona a double), y me cuentas. Yo voy a hacer lo propio, me ha picado el gusanillo.

Saludos,
  #3 (permalink)  
Antiguo 17/02/2013, 22:12
 
Fecha de Ingreso: junio-2005
Ubicación: Argentina
Mensajes: 90
Antigüedad: 18 años, 11 meses
Puntos: 2
Respuesta: Números Subnormales en C (estándar C99 y GCC 4.7)

Hola.

Gracias por la respuesta. Lamento no haber contestado antes.

Entiendo lo que decís de los 80 bits y el formato interno que se va a long double, etc.

Eso más o menos me imaginaba que funcionaba así.
Pero la duda que tengo va por otro lado.

¿El estándar C99 admite que fpclassify() dé un valor erróneo?
¿O acaso el compilador GCC 4.7 está mal hecho?

Hay algo que tiene que quedar bien claro, y es que acá lo que pasa con las máquinas reales no tiene ninguna importancia.
El estándar, en este caso el C99, está escrito en unas hojas de papel, sellado, firmado y metido en un cajón de alguna oficina de estándares quién sabe donde.
Es una serie de especificaciones dadas de tal suerte que, un compilador real, y una máquina real, las cumplen o no las cumplen.

Es lo mismo que los 10 mandamientos. Una persona religiosa "ideal" sería la que cumple esas 10 reglas. Pero tal persona no existe, y entonces el problema está en la persona.

Acá lo mismo, lo que quiero saber yo es si estoy entendiendo mal el alcance o el sentido exacto del estándar C99,
o si el compilador está mal hecho, y en tal caso hay que reportarlo como un bug.

____________

En un cierto momento mencionaste algo del tamaño del long double.

Ya que te picó el gusanillo, te invito a que le hagas un sizeof a una constante float, lo cual a mí me da de 4 bytes, pero que al compararla con una variable float que almacena la misma constante float, da que son distintos.

Mäs concreto:

float x = 1.1F;

printf("x == 1.1F?? %s", (x == 1.1F)? "SI":"NO");

_____________

Si le hacés un sizeof tanto a la variable x como a la constante 1.1F, en ambos casos te da 4 bytes.
De manera que el "redondeo" a "float" está hecho, aparentemente, de la misma manera.
Por lo tanto, internamente, tendrían que ser números binarios iguales,
sin importar que hay cosas "extrañas" con los números de punto flotante.

Si fuera todo como uno se lo imagina, en que la constante internamente se almacena por un rato en un registro de 12 bytes, entonces el sizeof de la constante tendría que darme de 12 bytes, pero no, da 4.

Pero si uno imprime el valor en hexadecimal de 1.1F con un printf() (hay que hacer un cast a long double para que imprima bien), lo que muestra es un valor que no está redondeado a la precisión de un "float", sino que conserva la precisión de long double.

Pareciera que en este caso el sufijo "F" de 1.1F no sirvió para nada.
Pero lo más extraño es esto de cómo diablos es posible que el sizeof() diga que sólo hay 4 bytes de información, mientras que se pueden visualizar 12 bytes.

Me imagino que la constante sigue estando almacenada en un registro punto flotante del procesador, o a lo mejor, si es que no me imagino estupideces, capaz que haya una copia en RAM del valor del registro de 12 bytes, pero sólo a modo de "copia temporal", y que el programa en realidad lo siga considerando un float, de 4 bytes.

Como sea, a mí me parece que en este ejemplo, el comportamiento del programa es correcto, en el sentido de que no contradice al estándar C99, sino que da un resultado admisible por dicho estándar.
Más precisamente, con un valor de FLT_EVAL_METHOD == 2,
es admisible, digo yo, que el compilador genere este comportamiento.

Y por lo tanto no sería un bug del compilador.

__________

Lo que sí me parece un posible bug del compilador GCC 4.7 es el comportamiento de fpclassify().

_________

En cuanto a cambiar el valor de FLT_EVAL_METHOD, no lo hice, y no porque sea difícil, sino que me parece que sólo conduce a engaños y desastres.
El valor de esa macro lo provee el compilador, no es algo que el programador debiera cambiar.
Está para darle información al programador, no para que el programador le ponga el valor que más le guste.

De hecho, es muy posible que se produzcan desajustes con la librería math.h y sus funciones aritméticas.

___________

Un saludo
  #4 (permalink)  
Antiguo 18/02/2013, 06:12
 
Fecha de Ingreso: junio-2010
Ubicación: Madrid
Mensajes: 620
Antigüedad: 13 años, 11 meses
Puntos: 73
Respuesta: Números Subnormales en C (estándar C99 y GCC 4.7)

En efecto, lo más probable es que cambiar el valor de FLT_EVAL_METHOD no sirva de nada y solamente sea informativo de cara al programador. Para cambiar ese comportamiento se necesitaría reconstruir el compilador, y probablemente sea una reminiscencia de la época en que las FPU eran opcionales y había librerías que emulaban la FPU cuando no la había. De todos modos, cambiarlo para probar no sería dañino. Si es meramente informativo para el programador, cambiarlo es como el que tiene hambre y se rasca la cabeza. Si no lo es, para el compilador será una indicación de cómo tratar los números en coma flotante, y ya tendrá previstos los casos posibles.

Sobre imprimir el valor en hexadecimal de 1.1F me extraña, que yo sepa el especificador de formato de printf para imprimir en hexadecimal es válido solamente para tipos enteros. No sé si Gcc lo permite para otros tipos, el compilador que tengo disponible en este momento (Lcc-Win32) no lo permite. En cualquier caso, si lo permite y has hecho un cast a long double, es lógico que te muestre 12 bytes, ya que lo que tienes tras el cast es un long double.

Las constantes y variables no se almacenan en registros del procesador ni de la FPU, ni hay copias en RAM de 12 bytas para las de coma flotante. El funcionamiento es:

- Las variables y constantes float/double se guardan en memoria ocupando los 4/8 bytes que corresponden por su tipo.

- Caundo la FPU las necesita, las lee de la memoria y las promociona a long double. Este valor promocionado es el que se guarda en un registro de la FPU mientras se utiliza en los cálculos.

- Una vez finalizados los cálculos, el resultado se "despromociona" a su tipo anterior y se guarda en la memoria correspondiente.

En cuanto a fpclassify() no he podido hacer pruebas, la máquina donde tenía Gcc está fuera de servicio. Cuando pueda haré más pruebas y ya comentaré.

Saludos,
  #5 (permalink)  
Antiguo 18/02/2013, 08:53
 
Fecha de Ingreso: junio-2005
Ubicación: Argentina
Mensajes: 90
Antigüedad: 18 años, 11 meses
Puntos: 2
Respuesta: Números Subnormales en C (estándar C99 y GCC 4.7)

Creo que no me he explicado.

El cast a long double se lo hice tanto a la constante 1.1F como a la variable x, la cual he definido, como se ve, de tipo "float", y a la que encima le cargué el mismo valor constante 1.1F.

En ambos casos, el printf() tiene que mostrar el mismo valor hexadecimal (eso creo yo), ya que todos los procesos que describís, de cargar en la FPU, luego en RAM, etc., tienen que ser los mismos en ambos casos.

Pero los valores que me muestra el printf() en hexadecimal, son distintos.
Los puse en hexadecimal, porque es más fácil entender lo que pasa a nivel de dígitos binarios.

Si realmente el problema fuera el cast que hice a long double, entonces la comparación que puse en el post anterior:

printf("x == 1.1F?? %s", (x == 1.1F)? "SI":"NO");

daría como resultado que "SI", pero en realidad da "NO".

O sea que a nivel interno a ambos valores "el compilador los ve" distintos.

______________

En cuanto a la posibilidad de visualizar valores flotantes en hexadecimal, con printf(),
es una característica que viene estipulada por el estándar C99,
y por lo tanto el GCC 4.7, con la opción de compilación -std=c99, tiene que tenerla incorporada.
Por eso el compilador la tiene, porque es su "obligación" adherirse a algo que ya viene dictado por el estándar.
_________________

En realidad el compilador GCC 4.7 con la opción de compilación -std=c99 incorpora casi todas las reglas que el estándar C99 estipula.
Pero los mismos desarrolladores del compilador dicen que todavía hay detalles que no han podido implementar correctamente.

En el caso de fpclassify(), si te fijás en la definición de esa macro,
vas a ver que la macro realmente intenta detectar números subnormales, para cada tipo de datos, ya sea float, double, long double.

Esto lo hace preguntando por el "tamaño" del dato, mediante un sizeof.
O sea, para saber si un dato X es de tipo "float", pregunta si sizeof(X) == sizeof(float), por ejemplo.

De modo que fpclassify() tendría que distinguir correctamente los casos en que uno tiene un float.

Aún así, no sé si es un bug, o está permitido por el estándar.

_____________

Yo sigo afirmando que la constante 1.1F queda guardada en algún "lugar", no sé cual, con un tamaño de 12 bytes de información, mientras que la variable x tiene sólo 4 bytes.

Es la única explicación que se me ocurre al hecho de que la comparación (x == 1.1F) da falso.

Por el contrario, por ejemplo la comparación (x == (float)(1.1F)) da verdadero.

La constante 1.1F es calculada por el procesador, se guarda el valor en algún lado, con la exactitud de un long double, con 12 bytes, además no le da importancia al sufijo F,.
Cuando le hago un sizeof me da que tiene 4 bytes, y cuando la comparo con x, me da falso.

Es de locos.

Otro detalle. Creo que el compilador directamente reconoce la constanta 1.1F como de tipo "long double".

Esto lo noté al poner a propósito algo erróneo como la operación (1.1F & 1), que me dio error, pero el compilador informa que la causa del error es que "1.1F es long double mientras 1 es int".
¿Y entonces, para qué el sufijo F de 1.1F? ¿No indica eso que la constante es "float"?

La duda que tengo es si, aunque aparentemente esto es un bug del compilador,
¿es de verdad un bug, o es algo que el estándar admite como una posibilidad dentro de las correctas?
Lo mismo me pasa con fpclassify.
¿Es un bug del compilador o no?
  #6 (permalink)  
Antiguo 18/02/2013, 09:05
 
Fecha de Ingreso: junio-2005
Ubicación: Argentina
Mensajes: 90
Antigüedad: 18 años, 11 meses
Puntos: 2
Respuesta: Números Subnormales en C (estándar C99 y GCC 4.7)

Cita:
- Una vez finalizados los cálculos, el resultado se "despromociona" a su tipo anterior y se guarda en la memoria correspondiente.
Bueno, esto no lo hace. A la constante 1.1F no la "despromociona" un pomo.

Yo quiero saber solamente si es un bug de GCC, o no lo es.
(Aunque igual me da curiosidad ahora de qué diablos está pasando internamente).

Porque si no lo es, entonces es el programador quien tiene la responsabilidad de tener en cuenta esas "anomalías", para programar sin errores.
Y si no, entonces hay que informar al equipo de desarrolladores de GCC, a ver si es posible que lo arreglen.

_______________

Hice lo que propusiste de cambiar la macro FLT_EVAL_METHOD a otro valor, le puse un 0.
Primero me tiró un "warning" de que esa macro había cambiado de valor (como que no le gustó), y además los resultados que obtengo son los mismos que antes.
O sea, no surtió efecto alguno.
El valor "2", que viene "de fábrica" (otorgado por GCC), hay que aguantárselo como viene.

Última edición por argentinator; 18/02/2013 a las 09:21
  #7 (permalink)  
Antiguo 20/02/2013, 05:18
 
Fecha de Ingreso: junio-2010
Ubicación: Madrid
Mensajes: 620
Antigüedad: 13 años, 11 meses
Puntos: 73
Respuesta: Números Subnormales en C (estándar C99 y GCC 4.7)

printf("x == 1.1F?? %s", (x == 1.1F)? "SI":"NO");

En mi sistema (Codeblocks 12.11 con MinGW (Gcc 4.7.1) en Win XP SP3) esa comparación me da correcta.

Sobre visualizar valores flotantes en Hex con printf, te agradecería me indicases cuál es el especificador de formato necesario.

En cuanto a la constante, hacer sizeof(1.1F) a mí me da 4 (8 si pongo simplemente sizeof(1.1)).

Las constantes no "despromocionan". Cuando se utilizan en cálculos con coma flotante, se hace una copia y se promociona la copia según convenga, pero la constante (como su nombre indica) no se toca, es de sólo lectura. Lo que sí "despromociona" son las variables que hayan cambiado de valor como consecuencia de los cálculos, al volver a guardar su valor después de finalizar los cálculos.

El estándar C99 es una recomendación, no hay ley alguna que obligue a seguirlo. Simplemente, es una forma de facilitar el aprendizaje del lenguaje y no tener que aprender un montón de cosas nuevas cada vez que cambias de sistema y/o compilador. Lógicamente, los cambios que haya respecto de lo anterior no pueden implementarse todos de golpe de la noche a la mañana y procurando mantener compatibilidad con las versiones anteriores (lo que puede elevar sobremanera el trabajo necesario). Además, ningún programa está (en principio) libre de bugs.

Sobre la macro FLT_EVAL_METHOD, en efecto, mirando en <math.h> he encontrado esto (Linea 314 del archivo, en mi instalación):

Código C:
Ver original
  1. /* Use the compiler's builtin define for FLT_EVAL_METHOD to
  2.    set float_t and double_t.  */
  3. #if defined(__FLT_EVAL_METHOD__)  
  4. # if ( __FLT_EVAL_METHOD__== 0)
  5. typedef float float_t;
  6. typedef double double_t;
  7. # elif (__FLT_EVAL_METHOD__ == 1)
  8. typedef double float_t;
  9. typedef double double_t;
  10. # elif (__FLT_EVAL_METHOD__ == 2)
  11. typedef long double float_t;
  12. typedef long double double_t;
  13. #endif
  14. #else /* ix87 FPU default */
  15. typedef long double float_t;
  16. typedef long double double_t;
  17. #endif

es decir, que está ya construída así en el compilador y no sirve de nada cambiarla, como ya has comprobado.

De todos modos, cuando se trata de operaciones en coma flotante, hay que tener cuidado con las comparaciones de igualdad. Por ejemplo, echa un vistazo a un post del 28-03-2012 (Validacion doble, de Alvarito_gool).

Saludos,
  #8 (permalink)  
Antiguo 20/02/2013, 17:36
 
Fecha de Ingreso: junio-2005
Ubicación: Argentina
Mensajes: 90
Antigüedad: 18 años, 11 meses
Puntos: 2
Respuesta: Números Subnormales en C (estándar C99 y GCC 4.7)

Hola.

Gracias por seguirme prestando atención con este asunto.

Es cierto que el estándar C99 es sólo una "recomendación".
Pero cuando el compilador GCC toma como opción de línea de comandos la opción -std=c99, entonces tiene que comportarse dentro de lo que el estándar obliga y/o permite.

No sé si fui claro con eso, pero yo estoy trabajando exclusivamente con esa opción del compilador, o sea, el estándar.
De hecho, cuando no pongo esa opción, la comparación me da correcta.

Ya sé que la constante no "despromociona", por eso lo puse entre comillas.
A veces soy algo cavernícola para explicar las cosas.
Lo que tal vez intento decir, más o menos, es que previamente hay un cálculo que convierte el decimal 1.1F a binario en alta precisión, y luego se lo redondea a la precisión de "float" dada por el sufijo "F".

Ya conozco los problemas de comparaciones con punto flotante.
Lo que me interesa discernir es qué dice el estándar al respecto, y si es consecuente con lo que obtengo con el compilador.

Creo que esto de la constante te lo había comentado a modo de curiosidad.

Mi duda va por el lado de la macro fpclassify().

______________

Para poder visualizar los valores de punto flotante en formato hexadecimal, se requiere compilar con la opción -std=c99, porque el estándar C99 es el que ha introducido esta nueva opción. Es con el especificador de formato %a.

Por ejemplo:

printf("%a", 1.23456); /* Muestra la constante en formato hexadecimal */
___________________

Mi queja, por llamarlo así, es acerca de la detección de números subnormales con fpclassify(),
la cual tiene que detectar correctamente el tipo de punto flotante,
o al menos la precisión del tipo (acorde al tamaño en bytes por ejemplo),
y luego indicar si el valor representado es subnormal o no lo es, para el rango de valores del tipo.

Les he planteado la cuestión a los desarrolladores de la implementación MinGW del GCC, y han dictaminado que es un tema pendiente de investigación.
Es más, creo que lo han aceptado como un bug, y planean corregirlo para la versión 4.1 de MinGW.

Por lo tanto yo consideraria que la pregunta original que hice en este hilo está resuelta.

Un saludo
  #9 (permalink)  
Antiguo 20/02/2013, 18:19
 
Fecha de Ingreso: junio-2005
Ubicación: Argentina
Mensajes: 90
Antigüedad: 18 años, 11 meses
Puntos: 2
Respuesta: Números Subnormales en C (estándar C99 y GCC 4.7)

Una leve aclaración a lo último que dije.

Aún no está clasificado como un "bug" lo que informé en MinGW.
Está pendiente como una "tarea", para ser investigado o revisado.
Hubiera querido que me den más detalles, pero lo analizarán más adelante.
  #10 (permalink)  
Antiguo 21/02/2013, 05:03
 
Fecha de Ingreso: junio-2010
Ubicación: Madrid
Mensajes: 620
Antigüedad: 13 años, 11 meses
Puntos: 73
Respuesta: Números Subnormales en C (estándar C99 y GCC 4.7)

Tenías razón con lo del flag -std=c99 y con fpclassify(), ejecuta este programilla y verás qué curioso lo que ocurre con la constante:

Código C:
Ver original
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <float.h>
  4. #include <math.h>
  5.  
  6. typedef struct
  7. {
  8.     unsigned    mnt : 23;   // Mantisa
  9.     unsigned    exp : 8;    // Exponente
  10.     unsigned    sgn : 1;    // Signo
  11. }
  12. Tflt;
  13.  
  14. typedef union
  15. {
  16.     int     intVal;
  17.     float   fltVal;
  18.     Tflt    bitVal;
  19. }
  20. Tval;
  21.  
  22. int main()
  23. {
  24.     Tval    x;
  25.  
  26.     printf("Sizeof(1.1F) = %d\n", sizeof(1.1F));
  27.     x.fltVal = 1.1F;
  28.     printf("X (FltHex)       = %a\n", x.fltVal);
  29.     printf("Cte (FltHex)     = %a\n", 1.1F);
  30.     printf("Cte (CastFltHex) = %a\n", (float)1.1F);
  31.     printf("Cte (DblHex)     = %a\n", 1.1);
  32.     printf("Cte (LDblHex)    = %La\n", 1.1L);
  33.     printf("X == 1.1F  ?? %s\n", (x.fltVal == 1.1F)? "SI":"NO");
  34.     printf("X == (float)1.1  ?? %s\n", (x.fltVal == (float)1.1F)? "SI":"NO");
  35.     printf("\n");
  36.     printf("X (flt) = %+f\n", x.fltVal);
  37.     printf("X (hex) = 0x%08X\n", x.intVal);
  38.     printf("X (sgn) = %u\n", x.bitVal.sgn);
  39.     printf("X (exp) = %u\n", x.bitVal.exp);
  40.     printf("X (mnt) = %06X\n", x.bitVal.mnt);
  41.     printf("X (fl2) = %a\n", x.fltVal);
  42.     printf("\n");
  43.     printf("Float   : FPCLASSIFY: %04X\n", fpclassify(FLT_MIN / (float)4.0));
  44.     printf("Double  : FPCLASSIFY: %04X\n", fpclassify(DBL_MIN / 4.0));
  45.     printf("LDouble : FPCLASSIFY: %04X\n", fpclassify(LDBL_MIN / 4.0L));
  46.     printf("\n");
  47.     printf("Float  : %e             FPCLASSIFY: %04X\n", FLT_MIN,  fpclassify(FLT_MIN / (float)4.0));
  48.     printf("Double : %e             FPCLASSIFY: %04X\n", DBL_MIN,  fpclassify(DBL_MIN / 4.0));
  49.     printf("LDouble con %%e  : %e   FPCLASSIFY: %04X\n", LDBL_MIN, fpclassify(LDBL_MIN / 4.0L));
  50.     printf("LDouble con %%Le : %Le   FPCLASSIFY: %04X\n", LDBL_MIN, fpclassify(LDBL_MIN / 4.0L));
  51.  
  52.     return 0;
  53. }

Como puedes ver, si le pido el tamaño de 1.1F me dice que 4 bytes, pero si le pido que me la imprima en hexadecimal lo hace como si tuviera 8 bytes, con lo que la comparación da negativo (pasando del sufijo). En cambio, casteando la constante la comparación da positivo.

Sobre fpclassify(), en la primera serie de printf me muestra 0x400 para float y double (que corresponde a FP_NORMAL) y 0x4400 para long double, que corresponde a FP_SUBNORMAL (que está definido como FP_NORMAL | FP_ZERO). Hasta aquí todo bien, pero fíjate qué curioso lo que sale en la segunda serie (imprimiendo previamente el valor mínimo para cada tipo), en el tercer printf.

Resumiendo:
Antes de meterse en palabras mayores con cálculos en coma flotante, habrá que hacer algunas minipruebas de este tipo para ver de qué pié cojea el compilador, independientemente del compilador, del estándar al que se adscriba, del sistema operativo y del procesador que se utilice.

Saludos,
  #11 (permalink)  
Antiguo 24/02/2013, 13:28
 
Fecha de Ingreso: febrero-2013
Mensajes: 3
Antigüedad: 11 años, 2 meses
Puntos: 0
Respuesta: Números Subnormales en C (estándar C99 y GCC 4.7)

alguien que me ayude con mi programa
http://www.forosdelweb.com/f96/tarea-c-1039027/

Etiquetas: gcc
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta

SíEste tema le ha gustado a 1 personas




La zona horaria es GMT -6. Ahora son las 01:50.