le plus grand entier qui peut être stocké dans un double

225

Quel est le plus grand entier "sans flottement" pouvant être stocké dans un type double IEEE 754 sans perte de précision?

Franck Freiburger
la source

Réponses:

506

Le plus grand / plus grand entier qui peut être stocké dans un double sans perte de précision est le même que la plus grande valeur possible d'un double. Autrement dit, DBL_MAXsoit environ 1,8 × 10 308 (si votre double est un double IEEE 754 64 bits). C'est un entier. Il est représenté exactement. Que veux-tu de plus?

Allez-y, demandez-moi quel est le plus grand entier, de sorte que lui et tous les plus petits entiers puissent être stockés dans des doubles IEEE 64 bits sans perdre en précision. Un double IEEE 64 bits a 52 bits de mantisse, donc je pense que c'est 2 53 :

  • 2 53 + 1 ne peuvent pas être stockés, car le 1 au début et le 1 à la fin ont trop de zéros entre les deux.
  • Tout ce qui est inférieur à 2 53 peut être stocké, avec 52 bits explicitement stockés dans la mantisse, puis l'exposant vous en donne un autre.
  • 2 53 peut évidemment être stocké, car c'est une petite puissance de 2.

Ou une autre façon de voir les choses: une fois que le biais a été supprimé de l'exposant, et en ignorant le bit de signe comme non pertinent pour la question, la valeur stockée par un double est une puissance de 2, plus un entier de 52 bits multiplié par 2 exposant - 52 . Ainsi, avec l'exposant 52, vous pouvez stocker toutes les valeurs de 2 52 à 2 53  - 1. Ensuite, avec l'exposant 53, le nombre suivant que vous pouvez stocker après 2 53 est 2 53 + 1 × 2 53 - 52 . La perte de précision se produit donc d'abord avec 2 53 + 1.

Steve Jessop
la source
126
+1 Bon travail en remarquant que la question ne voulait pas vraiment dire ce que le demandeur avait probablement l'intention et en fournissant les deux réponses ("techniquement correct" et "probablement attendu").
Pascal Cuoq
62
Ou "déconner" et "essayer d'aider" comme j'ai tendance à les appeler :-)
Steve Jessop
8
Je m'incline devant Tony le poney, et pas d'autre.
Steve Jessop
11
Vous ne voulez pas dire "tous les plus petits entiers", vous voulez dire tous les entiers de magnitude égale ou moindre. Parce qu'il y a beaucoup d'entiers négatifs en dessous de 2 ^ 53 et ne peuvent pas être représentés exactement en double.
Southern Hospitality
13
Je veux dire plus petit, et c'est exactement ce que je veux dire quand je dis plus petit: -) -1 000 000 est inférieur à 1, mais ce n'est pas plus petit.
Steve Jessop
77

9007199254740992 (c'est-à-dire 9,007,199,254,740,992) sans aucune garantie :)

Programme

#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;
}

Résultat

9007199254740991
9007199254740992
9007199254740992
pmg
la source
7
En supposant qu'il sera `` proche '' mais inférieur à un 2 ^ N, un test plus rapide est alors double dbl = 1; while (dbl + 1 != dbl) dbl *= 2; while (dbl == --dbl);qui donne le même résultat
Seph
4
@Seph qu'est-ce que ...? Non? while (dbl == --dbl)va boucler pour toujours ou pas du tout. :) (dans ce cas, pas du tout, puisqu'il s'agit d'un 2 ^ N). Vous devrez l'approcher par le bas. Il en résultera en effet également un de moins que le résultat attendu (puisque le seul contrôle dans la boucle while décrémente dbl). Et cela dépend de l'ordre d'exécution, si la décrémentation est effectuée avant ou après l'évaluation du côté gauche (qui n'est pas défini pour autant que je sache). Si c'est le premier, ce sera toujours vrai et boucle pour toujours.
falstro
10
Peut-être indiquer que 2 ^ 53 = 9,007,199,254,740,992 quelque part.
Xonatron
1
Il est difficile de contester cela! Belle expérience
MattM
Une faiblesse à utiliser while (dbl + 1 != dbl) dbl++;qui dbl + 1 != dblpeut évaluer l'utilisation des long doublemathématiques - considérez FLT_EVAL_METHOD == 2. Cela pourrait se terminer par une boucle infinie.
chux
25

Wikipedia a ceci à dire dans le même contexte avec un lien vers IEEE 754 :

Sur un système informatique typique, un nombre à virgule flottante binaire à double précision (64 bits) a un coefficient de 53 bits (dont un est implicite), un exposant de 11 bits et un bit de signe.

2 ^ 53 est un peu plus de 9 * 10 ^ 15.

Carl Smotricz
la source
@Steve Jessop plus ou moins, c'est bien ce que je dis. J'ai également rencontré des systèmes matériels qui n'ont pas de FPU qui doivent encore être conformes à IEEE, de sorte que les choses "système typique" ne m'aident pas vraiment si je reviens ici 8 mois plus tard et j'ai besoin des mêmes informations pour mon microcontrôleur basé sur 68K (en supposant qu'il n'a pas de FPU ... je ne me souviens pas).
San Jacinto
14
@San Jacinto - "C'est inutile" est indûment sévère. La réponse est assez utile, mais pas aussi utile qu'elle l'aurait été si elle incluait le commentaire selon lequel les systèmes informatiques typiques utilisent effectivement la représentation IEEE 754.
Stephen C. Steel,
@Stephen C. Steel, en fait vous avez raison. Dans mon scénario, en y revenant plus tard et en recherchant l'IEEE max, il est incroyablement ambigu quant à ce qu'est un `` système typique '', mais il y a toujours du mérite dans la réponse à part cette plainte.
San Jacinto
20

Le plus grand entier qui peut être représenté dans IEEE 754 double (64 bits) est le même que la plus grande valeur que le type peut représenter, car cette valeur est elle-même un entier.

Ceci est représenté par 0x7FEFFFFFFFFFFFFF, qui se compose de:

  • Le bit de signe 0 (positif) plutôt que 1 (négatif)
  • L'exposant maximum 0x7FE(2046 qui représente 1023 après la soustraction du biais) plutôt que 0x7FF(2047 qui indique un NaNou l'infini).
  • La mantisse maximale 0xFFFFFFFFFFFFFqui est de 52 bits tous les 1.

En binaire, la valeur est le 1 implicite suivi de 52 autres de la mantisse, puis 971 zéros (1023 - 52 = 971) de l'exposant.

La valeur décimale exacte est:

179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368

Cela représente environ 1,8 x 10 308 .

Simon Biber
la source
Qu'en est-il de la plus grande valeur qu'il peut représenter avec toutes les valeurs entre lui et zéro représentable de façon contiguë?
Aaron Franke
@AaronFranke La question ne portait pas sur la représentation contiguë, mais la réponse à cette question différente a été incluse dans la plupart des autres réponses ici, ou même incorrectement donnée comme réponse réelle. C'est 2⁵³ (2 pour la puissance de 53).
Simon Biber
8

Vous devez regarder la taille de la mantisse. Un nombre à virgule flottante 64 bits IEEE 754 (qui a 52 bits, plus 1 implicite) peut représenter exactement des entiers avec une valeur absolue inférieure ou égale à 2 ^ 53.

Dauphin
la source
8
Il peut aussi représenter exactement 2 ^ 53 :-)
Steve Jessop
6

1,7976931348623157 × 10 ^ 308

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

Geai
la source
2
cette réponse serait bien meilleure avec une citation.
San Jacinto
2
@Carl bien, si l'entier a des zéros au-delà à gauche, alors il est stocké avec précision.
Wilhelm
4
@tous les votants: 1.7976931348623157 × 10 ^ 308 est un entier exact. Avez-vous tous besoin de suivre des cours de rattrapage en mathématiques ou quelque chose comme ça ??
Dan Moulding,
6
Nous en sommes à la sémantique ici dans la discussion de cette réponse irrécupérable. Certes, ce nombre peut être représenté exactement et remplit ainsi la lettre de la question. Mais nous savons tous que c'est une minuscule île d'exactitude dans un océan de quasi-accidents, et la plupart d'entre nous ont correctement interpolé la question pour signifier "le plus grand nombre au-delà duquel la précision descend dans les égouts". Ah, n'est-ce pas merveilleux que CompSci soit une science exacte? :)
Carl Smotricz
2
@DanMoulding 1.7976931348623157 × 10 ^ 308 est un entier exact, mais je suis sûr que cet entier particulier ne peut pas être stocké exactement dans un double.
Pascal Cuoq
2

DECIMAL_DIGde <float.h>devrait en donner au moins une approximation raisonnable. Étant donné que cela concerne les chiffres décimaux et qu'il est vraiment stocké en binaire, vous pouvez probablement stocker quelque chose d'un peu plus grand sans perdre en précision, mais exactement combien est difficile à dire. Je suppose que vous devriez pouvoir le comprendre à partir de FLT_RADIXet DBL_MANT_DIG, mais je ne suis pas sûr que je ferais entièrement confiance au résultat.

Jerry Coffin
la source
Cela ne fournit pas de réponse à la question. Pour critiquer ou demander des éclaircissements à un auteur, laissez un commentaire sous son article.
MichaelChirico
@MichaelChirico: Cela répond à la question qu'il avait l'intention de poser, telle qu'elle existait lorsque la réponse a été écrite. Pour voir l'historique des modifications de la question, cliquez sur le lien "modifié le 19 juin 14 à 11:40" au bas de la question.
Jerry Coffin
votre réponse se lit comme un commentaire car elle semble manquer de confiance / d'autorité qu'une réponse devrait avoir ("devrait donner au moins un raisonnable ..." "exactement combien ... est difficile à dire" "je suppose ... "). Je n'ai aucune expertise sur la question posée ou la réponse, donc je peux me tromper; Je viens de mettre mes deux cents étant donné que j'ai été envoyé ici depuis la file d'attente (ce qui signifie que les autres utilisateurs ont signalé votre réponse).
MichaelChirico
1
@MichaelChirico: Ils ont peut-être bien - vous êtes loin d'être le seul à ignorer le sujet; ce qui vous rend inhabituel, c'est que vous vous rendez compte que vous l'ignorez. La plupart des réponses qui font autorité sur la précision d'un nombre à virgule flottante en C sont tout simplement erronées. Par exemple, beaucoup (la plupart) d'entre eux ci-dessus sont basés sur l'hypothèse fausse que a doublecorrespond directement à un type IEEE spécifique, mais ce n'est pas obligatoire, et lorsque cette réponse a été écrite, la question ne mentionnait pas non plus un type IEEE particulier.
Jerry Coffin
je l'ai. Je suggérerais peut-être d'ajouter cette information à la réponse.
MichaelChirico