Quel est le premier entier qu'un flottant IEEE 754 est incapable de représenter exactement?

164

Pour plus de clarté, si j'utilise un langage qui implémente les flottants IEE 754 et que je déclare:

float f0 = 0.f;
float f1 = 1.f;

... puis réimprimez-les, j'obtiendrai 0,0000 et 1,0000 - exactement.

Mais IEEE 754 n'est pas capable de représenter tous les nombres le long de la ligne réelle. Proche de zéro, les «écarts» sont petits; à mesure que vous vous éloignez, les écarts se creusent.

Donc, ma question est: pour un float IEEE 754, quel est le premier entier (le plus proche de zéro) qui ne peut pas être représenté exactement? Je ne suis vraiment concerné que par les flottants 32 bits pour le moment, même si je serai intéressé d'entendre la réponse pour 64 bits si quelqu'un la donne!

Je pensais que ce serait aussi simple que de calculer 2 bits_of_mantissa et d'ajouter 1, où bits_of_mantissa est le nombre de bits que la norme expose. Je l'ai fait pour les flottants 32 bits sur ma machine (MSVC ++, Win64), et cela semblait bien, cependant.

Floomi
la source
Pourquoi en avez-vous ajouté un si vous vouliez un nombre irreprésentable? Et quel numéro avez-vous utilisé ou obtenu? Et est-ce un devoir? Et le titre de votre question dit "entier" mais votre question dit "flottant".
msw
5
Parce que je pensais que maximiser la mantisse me donnerait le nombre représentable le plus élevé. 2 ^ 22. Non, c'est une question de curiosité. Je me suis toujours senti coupable de mettre des entiers dans des flotteurs, même quand je sais que l'int en question sera toujours très petit. Je veux savoir quelle est la limite supérieure. Pour autant que je sache, le titre et la question sont les mêmes, juste formulés différemment.
Floomi
1
duplicata de stackoverflow.com/questions/1848700/... ?
FrankH.
1
@KyleStrand est revenu ^ 2. Je ne sais pas pourquoi l'un me semblait plus correct que l'autre à l'époque. Maintenant, ils semblent tous les deux gênants par rapport à «… est le nombre de bits…»
Pascal Cuoq

Réponses:

211

2 bits de mantisse + 1 + 1

Le +1 dans l'exposant (bits de mantisse + 1) est dû au fait que, si la mantisse contient abcdef...le nombre qu'elle représente en fait 1.abcdef... × 2^e, il fournit un bit de précision implicite supplémentaire.

Par conséquent, le premier entier qui ne peut pas être représenté avec précision et qui sera arrondi est:
Pour float, 16 777 217 (2 24 + 1).
Pour double9 007 199 254 740 993 (2 53 + 1).

>>> 9007199254740993.0
9007199254740992
KennyTM
la source
J'ai déclaré a floatet l' ai fixé à 16 777 217. Mais quand je l'ai imprimé en l'utilisant, coutil en a résulté 16 777 216. J'utilise C++. Pourquoi ne puis-je pas obtenir 16 777 217?
nitrate de sodium
18
@sodiumnitrate Vérifiez le titre de la question. 16777217 est le premier entier incapable d'être représenté exactement.
kennytm
OK merci. Je suis confus, désolé à ce sujet. J'ai une autre question cependant: après 16777216, le prochain entier qui est représentable ne devrait-il pas être 2 * 16777216? Lorsque j'exécute un programme similaire, j'obtiens 16777218 en ajoutant 2 à 16777126.
sodiumnitrate
5
Le prochain entier est en effet 16777218, car 2 devient maintenant le dernier chiffre binaire significatif.
kennytm
6
En C ++, qui est (1 << std::numeric_limits<float>::digits) + 1, et en C, (1 << FLT_MANT_DIG) + 1. Le premier est sympa car il peut faire partie d'un modèle. N'ajoutez pas le +1 si vous voulez juste le plus grand entier représentable.
Henry Schreiner
38

La plus grande valeur représentable par un entier de n bits est 2 n -1. Comme indiqué ci-dessus, a floata 24 bits de précision dans le significande, ce qui semble impliquer que 2 24 ne rentre pas.

Cependant .

Les puissances de 2 dans la plage de l'exposant sont exactement représentables comme 1,0 × 2 n , donc 2 24 peut s'adapter et par conséquent le premier entier non représentable pour floatest 2 24 +1. Comme indiqué ci-dessus. Encore.

ainsi parlé ak
la source
1
Cela expliquait clairement la partie «extra implicite de précision» de l'autre. Merci.
chappjc