ejemplos - printf c
El valor flotante positivo mínimo por cálculo directo es diferente de FLT_MIN en<float.h> (2)
Quiero calcular directamente el valor mínimo del tipo float
, y aquí está mi algoritmo (Supongamos que la codificación del número de punto flotante confirma al estándar IEEE 754):
#include <math.h>
#include <limits.h>
#include <float.h>
#include <stdio.h>
float float_min()
{
int exp_bit = CHAR_BIT * sizeof(float) - FLT_MANT_DIG;
float exp = 2 - pow(2, exp_bit - 1);
float m = pow(2, -(FLT_MANT_DIG - 1));
return m * pow(2, exp);
}
int main()
{
printf("%g/n", float_min());
}
La salida es 1.4013e-45
. Sin embargo, encuentro que el valor de FLT_MIN
en C:/Program Files (x86)/Microsoft Visual Studio 12.0/VC/include/float.h
es 1.175494351e-38F
. Quien esta equivocado
Aunque esta pregunta se ha formulado y respondido varias veces antes, no veo ninguna respuesta que sea realmente correcta. La clave es que FLT_MIN
es el valor normalizado más pequeño que se puede representar. En los viejos tiempos eso era todo lo que importaba. Luego apareció Intel e introdujo valores subnormales , que reducen la precisión para representar valores más cercanos a 0. Los subnormales son valores con el exponente mínimo y una fracción cuyos bits altos son todos ceros. De ello se deduce que el valor subnormal no cero más pequeño tiene una fracción que es todos ceros excepto el bit más bajo, que es un 1. Ese es el valor más pequeño que puede representarse, pero cuando estás abajo, cambia un poco aquí. y se produce un gran cambio en el valor, por lo que estas cosas deben usarse con mucho cuidado.
EDITAR, para aclarar la "normalización":
Supongamos que estamos escribiendo valores decimales: 6.02x10 ^ 23, .602 * 10 ^ 24, 60.2 * 10 ^ 22. Todos ellos representan el mismo valor, pero claramente se ven diferentes. Entonces, introduzcamos una regla para escribir valores decimales: cada valor debe tener exactamente un dígito distinto de cero a la izquierda del punto decimal. Entonces, la forma "normalizada" de ese valor es 6.02x10 ^ 23, y si tenemos un valor escrito en una forma no normalizada, podemos mover el punto decimal y ajustar el exponente para preservar el valor y ponerlo en forma normalizada.
El punto flotante de IEEE hace lo mismo: la regla es que el bit alto de la fracción siempre debe ser 1, y cualquier cálculo debe ajustar la fracción y el exponente de su resultado para satisfacer esa regla.
Cuando escribimos valores decimales que están muy cerca de 0, eso no es un problema: podemos hacer que el exponente sea tan pequeño como sea necesario, por lo que podemos escribir números como 6.02 * 10 ^ -16384. Con valores de punto flotante no podemos hacer eso: hay un mínimo exponente al que no podemos ir abajo. Para permitir valores más pequeños, los requisitos de IEEE dicen que cuando el exponente es el valor representable más pequeño, la fracción no tiene que normalizarse, es decir, no tiene que tener un 1 en su bit más alto. Al escribir valores decimales, es como decir que podemos tener un 0 a la izquierda del punto decimal. Entonces, si nuestra regla decimal dice que el exponente más bajo permitido es -100, el valor normalizado más pequeño sería 1.00x10 ^ -100, pero el valor más pequeño podría representarse como no normalizado: 0.10 * 10 ^ -100, 0.01 * 10 ^ 100, etc.
Ahora agregue un requisito a nuestras reglas decimales de que solo podemos tener tres dígitos: uno a la izquierda del punto decimal y dos a la derecha. Eso es como la fracción de punto flotante en que tiene un número fijo de dígitos. Entonces, para valores normales pequeños, tenemos tres dígitos para jugar: 1.23 * 10 ^ -100. Para valores más pequeños, utilizamos ceros a la izquierda, y los dígitos restantes tienen menos precisión: 0.12 * 10 ^ -100 tiene dos dígitos, y 0.01 * 10 ^ -100 tiene solo 1. También es así como funcionan los subnormales de punto flotante: obtienes menos y menos bits significativos a medida que se va alejando más y más del valor normalizado mínimo, hasta que se quede sin bits y obtenga 0.
EDITAR: para aclarar la terminología, el estándar IEEE-754 se refiere a aquellos valores que son mayores que 0 y menos que el valor normalizado mínimo como denormales ; La última revisión de IEEE-754 se refiere a ellos como subnormales . Quieren decir lo mismo.
Su resultado 1.4013e-45
es un valor flotante positivo mínimo denormal, también conocido como FLT_TRUE_MIN
que es igual a 1.401298464e-45F
.
FLT_MIN
es un valor flotante positivo mínimo normalizado ( 1.175494351e-38F
)