Ver Mensaje Individual
  #3 (permalink)  
Antiguo 17/02/2013, 22:12
argentinator
 
Fecha de Ingreso: junio-2005
Ubicación: Argentina
Mensajes: 90
Antigüedad: 19 años, 5 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