Quel est le plus grand entier "sans flottement" pouvant être stocké dans un type double IEEE 754 sans perte de précision?
Quel est le plus grand entier "sans flottement" pouvant être stocké dans un type double IEEE 754 sans perte de précision?
Réponses:
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_MAX
soit 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 :
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.
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
double dbl = 1; while (dbl + 1 != dbl) dbl *= 2; while (dbl == --dbl);
qui donne le même résultat
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.
while (dbl + 1 != dbl) dbl++;
qui dbl + 1 != dbl
peut évaluer l'utilisation des long double
mathématiques - considérez FLT_EVAL_METHOD == 2
. Cela pourrait se terminer par une boucle infinie.
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.
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:
0x7FE
(2046 qui représente 1023 après la soustraction du biais) plutôt que 0x7FF
(2047 qui indique un NaN
ou l'infini).0xFFFFFFFFFFFFF
qui 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 .
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.
1,7976931348623157 × 10 ^ 308
http://en.wikipedia.org/wiki/Double_precision_floating-point_format
DECIMAL_DIG
de <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_RADIX
et DBL_MANT_DIG
, mais je ne suis pas sûr que je ferais entièrement confiance au résultat.
double
correspond 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.