Pas vraiment spécifique à l'implémentation de Python mais devrait s'appliquer à toutes les fonctions de chaîne flottante à décimale.
Un nombre à virgule flottante est essentiellement un nombre binaire, mais en notation scientifique avec une limite fixe de chiffres significatifs.
L'inverse de tout nombre qui a un facteur de nombre premier qui n'est pas partagé avec la base se traduira toujours par une représentation de point de point récurrente. Par exemple 1/7 a un facteur premier, 7, qui n'est pas partagé avec 10, et a donc une représentation décimale récurrente, et il en va de même pour 1/10 avec les facteurs premiers 2 et 5, ce dernier n'étant pas partagé avec 2 ; cela signifie que 0,1 ne peut pas être représenté exactement par un nombre fini de bits après le point.
Étant donné que 0,1 n'a pas de représentation exacte, une fonction qui convertit l'approximation en chaîne de virgule décimale essaiera généralement d'approximer certaines valeurs afin qu'elles n'obtiennent pas de résultats non intuitifs tels que 0.1000000000004121.
Puisque la virgule flottante est en notation scientifique, toute multiplication par une puissance de la base n'affecte que la partie exposante du nombre. Par exemple 1.231e + 2 * 100 = 1.231e + 4 pour la notation décimale, et de même, 1.00101010e11 * 100 = 1.00101010e101 en notation binaire. Si je multiplie par une non-puissance de la base, les chiffres significatifs seront également affectés. Par exemple 1,2e1 * 3 = 3,6e1
Selon l'algorithme utilisé, il peut essayer de deviner les décimales communes en se basant uniquement sur les chiffres significatifs. 0,1 et 0,4 ont les mêmes chiffres significatifs en binaire, car leurs flotteurs sont essentiellement des troncatures de (8/5) (2 ^ -4) et (8/5) (2 ^ -6) respectivement. Si l'algorithme identifie le motif 8/5 sigfig comme le décimal 1,6, alors il fonctionnera sur 0,1, 0,2, 0,4, 0,8, etc. et d'autres modèles magiques statistiquement susceptibles d'être formés par division par 10.
Dans le cas de 3 * 0,1, les derniers chiffres significatifs seront probablement différents de la division d'un flotteur 3 par un flotteur 10, ce qui empêchera l'algorithme de reconnaître le nombre magique de la constante 0,3 en fonction de sa tolérance à la perte de précision.
Modifier:
https://docs.python.org/3.1/tutorial/floatingpoint.html
Fait intéressant, il existe de nombreux nombres décimaux différents qui partagent la même fraction binaire approximative la plus proche. Par exemple, les nombres 0.1 et 0.10000000000000001 et 0.1000000000000000055511151231257827021181583404541015625 sont tous approximés par 3602879701896397/2 ** 55. Étant donné que toutes ces valeurs décimales partagent la même approximation, n'importe laquelle d'entre elles peut être affichée tout en préservant l'évaluation invariante (repr (x) ) == x.
Il n'y a pas de tolérance pour la perte de précision, si float x (0,3) n'est pas exactement égal à float y (0,1 * 3), alors repr (x) n'est pas exactement égal à repr (y).