mayor entero que se puede almacenar en un doble

Respuestas:

506

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_MAXo 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 :

  • 2 53 + 1 no se puede almacenar, porque el 1 al inicio y el 1 al final tienen demasiados ceros en el medio.
  • Cualquier cosa menos que 2 53Se puede almacenar , con 52 bits almacenados explícitamente en la mantisa, y luego el exponente en efecto le da otro.
  • 2 53 obviamente se puede almacenar, ya que es una pequeña potencia de 2.

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.

Steve Jessop
fuente
126
+1 Buen trabajo al darse cuenta de que la pregunta realmente no significaba lo que el autor de la pregunta probablemente pretendía y proporcionar ambas respuestas ("técnicamente correcto" y "probablemente esperado").
Pascal Cuoq
62
O "perder el tiempo" y "tratar de ayudar" como suelo llamarlos :-)
Steve Jessop
8
Me inclino ante Tony el Pony, y no otro.
Steve Jessop el
11
No quiere decir "todos los enteros más pequeños", se refiere a todos los enteros de igual o menor magnitud. Porque hay muchos enteros negativos debajo de 2 ^ 53 y no se pueden representar exactamente en un doble.
Southern Hospitality
13
Quiero decir más pequeño, y eso es exactamente lo que quiero decir cuando digo más pequeño :-) -1,000,000 es menos de 1, pero no es más pequeño.
Steve Jessop
77

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
pmg
fuente
77
Suponiendo que estará 'cerca' pero menos de 2 ^ N, entonces una prueba más rápida es la double dbl = 1; while (dbl + 1 != dbl) dbl *= 2; while (dbl == --dbl);que produce el mismo resultado
Seph
44
@Seph, ¿qué demonios ...? ¿No? 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.
falstro
10
Quizás indique que 2 ^ 53 = 9,007,199,254,740,992 en alguna parte.
Xonatron
1
¡Es difícil discutir con esto! Buen experimento
MattM
Una debilidad para usar while (dbl + 1 != dbl) dbl++;en eso dbl + 1 != dblpuede evaluar el uso de las long doublematemáticas: considere FLT_EVAL_METHOD == 2. Esto podría terminar en un bucle infinito.
chux
25

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.

Carl Smotricz
fuente
@ Steve Jessop más o menos, eso es lo que estoy diciendo. También me he encontrado con sistemas de hardware que no tienen una FPU que todavía necesitan ser compatibles con IEEE, por lo que las cosas del "sistema típico" realmente no me ayudan si vuelvo aquí 8 meses después y necesito la misma información para mi microcontrolador basado en 68K (suponiendo que no tenga una FPU ... no me acuerdo).
San Jacinto
14
@San Jacinto - "Esto es inútil" es excesivamente duro. La respuesta es bastante útil, pero no tan útil como lo hubiera sido si incluyera el comentario de que los sistemas informáticos típicos sí usan la reprensentación IEEE 754.
Stephen C. Steel, el
@Stephen C. Steel, en realidad tienes razón. Bajo mi escenario, volviendo a esto más adelante y buscando el IEEE max, es imposiblemente ambiguo en cuanto a qué es un 'sistema típico', pero aún hay mérito en la respuesta además de esta queja.
San Jacinto
20

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:

  • El bit de signo 0 (positivo) en lugar de 1 (negativo)
  • El exponente máximo 0x7FE(2046 que representa 1023 después de restar el sesgo) en lugar de 0x7FF(2047 que indica ao NaNinfinito).
  • La mantisa máxima 0xFFFFFFFFFFFFFque 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 .

Simon Biber
fuente
¿Qué pasa con el valor más grande que puede representar con todos los valores entre él y cero representable contiguamente?
Aaron Franke
@AaronFranke La pregunta no preguntó sobre la representación contigua, pero la respuesta a esa pregunta diferente se ha incluido en la mayoría de las otras respuestas aquí, o incluso se ha dado erróneamente como la respuesta real. Es 2⁵³ (2 a la potencia de 53).
Simon Biber
8

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.

Delfín
fuente
8
También puede representar exactamente 2 ^ 53 :-)
Steve Jessop
6

1.7976931348623157 × 10 ^ 308

http://en.wikipedia.org/wiki/Double_precision_floating-point_format

Arrendajo
fuente
2
Esta respuesta sería mucho mejor con una cita.
San Jacinto
2
@Carl bien, si el entero tiene ceros más allá a la izquierda, entonces se almacena con precisión.
Wilhelm
44
@todos ustedes downvoters: 1.7976931348623157 × 10 ^ 308 es un entero exacto. ¿Todos necesitan asistir a clases de recuperación de matemáticas o algo así?
Dan Moulding
66
Estamos abajo a la semántica aquí en la discusión de esta respuesta irremediablemente hundida. Es cierto que ese número puede representarse exactamente y, por lo tanto, cumple con la letra de la pregunta. Pero todos sabemos que es una pequeña isla de exactitud en un océano de casi accidentes, y la mayoría de nosotros interpolamos correctamente la pregunta para que signifique "el mayor número más allá del cual la precisión se va por el desagüe". Ah, ¿no es maravilloso que CompSci sea una ciencia exacta? :)
Carl Smotricz
2
@DanMoulding 1.7976931348623157 × 10 ^ 308 es un entero exacto, pero estoy bastante seguro de que este entero en particular no se puede almacenar exactamente en un doble.
Pascal Cuoq
2

DECIMAL_DIGdesde <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_RADIXy DBL_MANT_DIG, pero no estoy seguro de confiar completamente en el resultado.

Jerry Coffin
fuente
Esto no proporciona una respuesta a la pregunta. Para criticar o solicitar una aclaración de un autor, deje un comentario debajo de su publicación.
MichaelChirico
@MichaelChirico: Esto responde a la pregunta que pretendía hacer, tal como existía cuando se escribió la respuesta. Para ver el historial de edición de la pregunta, haga clic en el enlace "editado el 19 de junio de 2014 a las 11:40" en la parte inferior de la pregunta.
Jerry Coffin
su respuesta se lee como un comentario porque parece carecer de la confianza / autoridad que debería tener una respuesta ("debería dar al menos un razonable ..." "exactamente cuánto ... es difícil de decir" "Supongo ... "). No tengo experiencia en la pregunta o la respuesta, por lo que puedo estar equivocado; solo ponía mis dos centavos dado que me enviaron aquí desde la cola de revisión (lo que supongo que significa que otros usuarios marcaron su respuesta).
MichaelChirico
1
@MichaelChirico: Es posible que lo hayan hecho: estás lejos de ser el único que ignora el tema; lo que te hace inusual es que te das cuenta de que lo ignoras. La mayoría de las respuestas que suenan autorizadas sobre la precisión de un número de coma flotante en C son simplemente erróneas. Por ejemplo, muchos (la mayoría) de los anteriores se basan en la suposición falsa de que a doublecorresponde 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.
Jerry Coffin
Entendido. Quizás sugiera agregar esa información a la respuesta.
MichaelChirico