Que cela fonctionne n'est pas anodin! C'est une propriété de la représentation en virgule flottante IEEE que int∘floor = ⌊⋅⌋ si la magnitude des nombres en question est suffisamment petite, mais différentes représentations sont possibles où int (floor (2.3)) pourrait être 1.
Ce post explique pourquoi cela fonctionne dans cette gamme .
Dans un double, vous pouvez représenter des entiers 32 bits sans aucun problème. Il ne peut y avoir de problème d'arrondi. Plus précisément, les doubles peuvent représenter tous les entiers compris entre 2 53 et -2 53 inclus .
Brève explication : un double peut stocker jusqu'à 53 chiffres binaires. Lorsque vous en avez besoin de plus, le nombre est complété par des zéros à droite.
Il s'ensuit que 53 unités est le plus grand nombre pouvant être stocké sans remplissage. Naturellement, tous les nombres (entiers) nécessitant moins de chiffres peuvent être stockés avec précision.
Ajouter un à 111 (omis) 111 (53 uns) donne 100 ... 000, (53 zéros). Comme nous le savons, nous pouvons stocker 53 chiffres, ce qui fait le remplissage zéro le plus à droite.
C'est de là que vient 2 53 .
Plus de détails: nous devons examiner comment fonctionne la virgule flottante IEEE-754.
1 bit 11 / 8 52 / 23 # bits double/single precision
[ sign | exponent | mantissa ]
Le nombre est ensuite calculé comme suit (hors cas particuliers qui ne sont pas pertinents ici):
-1 signe × 1.mantisse × 2 exposant - biais
où biais = 2 exposants - 1 - 1 , c'est-à-dire 1023 et 127 pour la précision double / simple respectivement.
Sachant que multiplier par 2 X décale simplement tous les bits X à gauche, il est facile de voir que tout entier doit avoir tous les bits de la mantisse qui se terminent à droite de la virgule décimale par zéro.
Tout entier sauf zéro a la forme suivante en binaire:
1x ... x où les x -es représentent les bits à droite du MSB (bit le plus significatif).
Parce que nous avons exclu zéro, il y aura toujours un MSB qui est un, c'est pourquoi il n'est pas stocké. Pour stocker l'entier, nous devons le mettre sous la forme susmentionnée: -1 signe × 1.mantisse × 2 exposant - biais .
Cela signifie la même chose que de déplacer les bits sur la virgule décimale jusqu'à ce qu'il n'y ait que le MSB vers la gauche du MSB. Tous les bits à droite de la virgule décimale sont ensuite stockés dans la mantisse.
De cela, nous pouvons voir que nous pouvons stocker au plus 52 chiffres binaires en dehors du MSB.
Il s'ensuit que le nombre le plus élevé où tous les bits sont explicitement stockés est
111(omitted)111. that's 53 ones (52 + implicit 1) in the case of doubles.
Pour cela, nous devons définir l'exposant, de sorte que la virgule décimale soit décalée de 52 places. Si nous devions augmenter l'exposant de un, nous ne pouvons pas connaître le chiffre de droite à gauche après le point décimal.
111(omitted)111x.
Par convention, c'est 0. En mettant la mantisse entière à zéro, nous recevons le nombre suivant:
100(omitted)00x. = 100(omitted)000.
C'est un 1 suivi de 53 zéros, 52 stockés et 1 ajouté en raison de l'exposant.
Il représente 2 53 , qui marque la frontière (à la fois négative et positive) entre laquelle nous pouvons représenter avec précision tous les entiers. Si nous voulions ajouter un à 2 53 , nous devions définir le zéro implicite (indiqué par le x
) à un, mais c'est impossible.
math.floor
renvoie un flottant dans la v2.6 , mais il renvoie un entier dans la v3 . À ce stade (près de six ans après le PO), ce problème pourrait apparaître rarement.