Estoy tratando de averiguar exactamente qué número grande puedo usar como número de punto flotante y double . Pero no almacena la forma en que esperaba, excepto el valor entero. double debería contener 8 bytes de información, que es suficiente para contener la variable a, pero no la mantiene correctamente. Muestra 1234567890123456768 en el que los últimos 2 dígitos son diferentes. Y cuando 214783648 o cualquier dígito en el último dígito en la variable flotante b , muestra el mismo valor 214783648 . que se supone que es el límite. Entonces, ¿qué está pasando?
double a; float b; int c; a = 1234567890123456789; b = 2147483648; c = 2147483647; printf("Bytes of double: %d\n", sizeof(double)); printf("Bytes of integer: %d\n", sizeof(int)); printf("Bytes of float: %d\n", sizeof(float)); printf("\n"); printf("You can count up to %.0f in 4 bytes\n", pow(2,32)); printf("You can count up to %.0f with + or - sign in 4 bytes\n", pow(2,31)); printf("You can count up to %.0f in 4 bytes\n", pow(2,64)); printf("You can count up to %.0f with + or - sign in in 8 bytes\n", pow(2,63)); printf("\n"); printf("double number: %.0f\n", a); printf("floating point: %.0f\n", b); printf("integer: %d\n", c); return 0;La respuesta a la pregunta de cuál es el número más grande (finito) que se puede almacenar en un tipo de coma flotante sería FLT_MAX o DBL_MAX para float y double , respectivamente.
Sin embargo, eso no significa que el tipo pueda representar con precisión cada número o entero más pequeño (de hecho, ni siquiera cerca).
Primero, debe comprender que no todos los bits de un número de punto flotante son "iguales". Un número de coma flotante tiene un exponente (8 bits en float estándar IEEE-754, 11 bits en double ) y una mantisa (23 y 52 bits en float y double respectivamente). El número se obtiene multiplicando la mantisa (que tiene un bit inicial implícito y un punto binario) por 2 exponentes (después de normalizar el exponente; su valor binario no se usa directamente). También hay un bit de signo separado, por lo que lo siguiente también se aplica a los números negativos.
A medida que cambia el exponente, también cambia la distancia entre los valores consecutivos de la mantisa, es decir, cuanto mayor es el exponente, más separados están los valores consecutivos representables del número de coma flotante. Por lo tanto, es posible que pueda almacenar con precisión un número de una determinada magnitud, pero no el "siguiente" número. También se debe recordar que algunas fracciones aparentemente simples no se pueden representar con precisión con ningún número de dígitos binarios (p. ej., 1/10 , un décimo, es una secuencia que se repite infinitamente en binario, como 1/3 , un tercio, es un decimal) .
Cuando se trata de números enteros, puede representar con precisión cada número entero hasta 2 mantissa_bits + 1 magnitud. Por lo tanto, un float IEEE-754 puede representar todos los enteros hasta 2 24 y un double hasta 2 53 (en la última mitad de estos rangos, los valores consecutivos de coma flotante están separados exactamente por un entero, ya que la mantisa completa se usa para la parte entera). solamente). Hay enteros individuales más grandes que se pueden representar, pero están separados por más de un entero, es decir, puede representar algunos enteros mayores que 2 mantissa_bits + 1 pero cada entero solo hasta esa magnitud.
Por ejemplo:
float f = powf(2.0f, 24.0f); float f1 = f + 1.0f, f2 = f1 + 2.0f; double d = pow(2.0, 53.0); double d1 = d + 1.0, d2 = d + 2.0; (void) printf("2**24 float = %.0f, +1 = %.0f, +2 = %.0f\n", f, f1, f2); (void) printf("2**53 double = %.0f, +1 = %.0f, +2 = %.0f\n", d, d1, d2);Salidas:
2**24 float = 16777216, +1 = 16777216, +2 = 16777218 2**53 double = 9007199254740992, +1 = 9007199254740992, +2 = 9007199254740994 Como puede ver, sumar 1 a 2 mantissa_bits + 1 no hace ninguna diferencia ya que el resultado no es representable, pero sumar 2 produce la respuesta correcta (da la casualidad de que en esta magnitud los números representables están separados por dos enteros ya que el multiplicador se ha duplicado ).
TL; DR Un float IEE-754 puede representar con precisión todos los números enteros hasta 2 24 y el double hasta 2 53 , pero solo algunos números enteros de mayor magnitud (el espaciado de los valores representables depende de la magnitud).
sizeof(double) es 8 , cierto, pero double también necesita algunos bits para almacenar la parte del exponente .
Suponiendo que se utiliza IEEE-754, double puede representar enteros como máximo 2 53 con precisión, que es menor que 1234567890123456789 .
Véase también Formato de punto flotante de precisión doble .
Puedes usar constantes para saber cuáles son los límites:
FLT_MAX DBL_MAX LDBL_MAX