¿Cuál es el número entero "no flotante" más grande que se puede almacenar en un tipo doble IEEE 754 sin perder precisión?
¿Cuál es el número entero "no flotante" más grande que se puede almacenar en un tipo doble IEEE 754 sin perder precisión?
Respuestas:
El entero más grande / más grande que se puede almacenar en un doble sin perder precisión es el mismo que el mayor valor posible de un doble. Es decir, DBL_MAX
o aproximadamente 1.8 × 10 308 (si su doble es un doble IEEE 754 de 64 bits). Es un entero. Está representado exactamente. ¿Qué más quieres?
Continúe, pregúnteme cuál es el número entero más grande, de modo que este y todos los números enteros más pequeños se puedan almacenar en dobles IEEE de 64 bits sin perder precisión. Un doble IEEE de 64 bits tiene 52 bits de mantisa, así que creo que es 2 53 :
O otra forma de verlo: una vez que se ha eliminado el sesgo del exponente, e ignorando el bit de signo como irrelevante para la pregunta, el valor almacenado por un doble es una potencia de 2, más un número entero de 52 bits multiplicado por 2 exponente - 52 . Entonces, con el exponente 52 puede almacenar todos los valores desde 2 52 hasta 2 53 - 1. Luego, con el exponente 53, el siguiente número que puede almacenar después de 2 53 es 2 53 + 1 × 2 53 - 52 . Entonces, la pérdida de precisión ocurre primero con 2 53 + 1.
9007199254740992 (eso es 9,007,199,254,740,992) sin garantías :)
Programa
#include <math.h>
#include <stdio.h>
int main(void) {
double dbl = 0; /* I started with 9007199254000000, a little less than 2^53 */
while (dbl + 1 != dbl) dbl++;
printf("%.0f\n", dbl - 1);
printf("%.0f\n", dbl);
printf("%.0f\n", dbl + 1);
return 0;
}
Resultado
9007199254740991 9007199254740992 9007199254740992
double dbl = 1; while (dbl + 1 != dbl) dbl *= 2; while (dbl == --dbl);
que produce el mismo resultado
while (dbl == --dbl)
se repetirá para siempre o para nada. :) (en este caso, para nada, ya que es un 2 ^ N). Tendrás que abordarlo desde abajo. De hecho, también dará como resultado uno menos que el resultado esperado (ya que la verificación en el ciclo while disminuye dbl). Y depende del orden de ejecución, si la disminución se realiza antes o después de evaluar el lado izquierdo (que no está definido hasta donde yo sé). Si es lo primero, siempre será cierto y se repetirá para siempre.
while (dbl + 1 != dbl) dbl++;
en eso dbl + 1 != dbl
puede evaluar el uso de las long double
matemáticas: considere FLT_EVAL_METHOD == 2
. Esto podría terminar en un bucle infinito.
Wikipedia tiene esto que decir en el mismo contexto con un enlace a IEEE 754 :
En un sistema informático típico, un número de punto flotante binario de 'doble precisión' (64 bits) tiene un coeficiente de 53 bits (uno de los cuales está implícito), un exponente de 11 bits y un bit de signo.
2 ^ 53 es un poco más de 9 * 10 ^ 15.
El número entero más grande que se puede representar en IEEE 754 doble (64 bits) es el mismo valor más grande que el tipo puede representar, ya que ese valor es en sí mismo un número entero.
Esto se representa como 0x7FEFFFFFFFFFFFFF
, que se compone de:
0x7FE
(2046 que representa 1023 después de restar el sesgo) en lugar de 0x7FF
(2047 que indica ao NaN
infinito).0xFFFFFFFFFFFFF
que es de 52 bits todos 1.En binario, el valor es el 1 implícito seguido de otros 52 unos de la mantisa, luego 971 ceros (1023 - 52 = 971) del exponente.
El valor decimal exacto es:
179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368
Esto es aproximadamente 1.8 x 10 308 .
Debes mirar el tamaño de la mantisa. Un número de coma flotante IEEE 754 de 64 bits (que tiene 52 bits, más 1 implícito) puede representar exactamente números enteros con un valor absoluto menor o igual a 2 ^ 53.
1.7976931348623157 × 10 ^ 308
http://en.wikipedia.org/wiki/Double_precision_floating-point_format
DECIMAL_DIG
desde <float.h>
debería dar al menos una aproximación razonable de eso. Dado que se trata de dígitos decimales, y realmente se almacena en binario, probablemente pueda almacenar algo un poco más grande sin perder precisión, pero exactamente cuánto es difícil de decir. Supongo que deberías poder resolverlo desde FLT_RADIX
y DBL_MANT_DIG
, pero no estoy seguro de confiar completamente en el resultado.
double
corresponde directamente a un tipo IEEE específico, pero eso no es obligatorio, y cuando se escribió esta respuesta, la pregunta tampoco mencionó un tipo IEEE en particular.