Exercice - niveau basique¶
Le plus petit flottant¶
En corollaire de la discussion sur la précision des flottants, il faut savoir que le système de codage en mémoire impose aussi une limite. Les réels très petits, ou très grands, ne peuvent plus être représentés de cette manière.
C’est notamment très gênant si vous implémentez un logiciel probabiliste, comme des graphes de Markov, où les probabilités d’occurrence de séquences très longues tendent très rapidement vers des valeurs extrêmement petites.
Le but de cet exercice est d’estimer la valeur du plus petit flottant qui peut être représenté comme un flottant. Pour vous aider, voici deux valeurs :
10**-3201e-32010**-3300.0Comme on le voit, 10-320 est correctement imprimé, alors que 10-330 est, de manière erronée, rapporté comme étant nul.
Notes :
À ce stade du cours, pour estimer le plus petit flottant, procédez simplement par approximations successives.
Sans utiliser de boucle, la précision que vous pourrez obtenir n’est que fonction de votre patience, ne dépassez pas 4 à 5 itérations successives :)
Il est par contre pertinent d’utiliser une approche rationnelle pour déterminer l’itération suivante (par opposition à une approche “au petit bonheur”). Pour ceux qui ne connaissent pas, nous vous recommandons de vous documenter sur l’algorithme de dichotomie.
10**-3250.0Voici quelques cellules de code vides ; vous pouvez en créer d’autres si nécessaire, le plus simple étant de taper Alt+Enter, ou d’utiliser le menu “Insert -> Insert Cell Below”
# vos essais successifs ici.24*10**-3230.0Le plus grand flottant¶
La même limitation s’applique sur les grands nombres. Toutefois, cela est un peu moins évident, car comme toujours il faut faire attention aux types :
10**4501000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000Ce qui passe très bien car j’ai utilisé un int pour l’exposant. Dans ce premier cas Python calcule le résultat comme un int, qui est un type qui n’a pas de limitation de précision (Python utilise intelligemment autant de bits que nécessaire pour ce genre de calculs).
Par contre, si j’essaie de faire le même calcul avec un exposant flottant, Python essaie cette fois de faire son calcul avec un flottant, et là on obtient une erreur :
10**450.0The history saving thread hit an unexpected error (OperationalError('attempt to write a readonly database')).History will not be written to the database.
---------------------------------------------------------------------------
OverflowError Traceback (most recent call last)
Cell In[7], line 1
----> 1 10**450.0
OverflowError: (34, 'Numerical result out of range')On peut d’ailleurs remarquer que le comportement ici n’est pas extrêmement cohérent, car avec les petits nombres Python nous a silencieusement transformé 10-330 en 0, alors que pour les grands nombres, il lève une exception (nous verrons les exceptions plus tard, mais vous pouvez dès maintenant remarquer que le comportement est différent dans les deux cas).
Quoi qu’il en soit, la limite pour les grands nombres se situe entre les deux valeurs 10300 et 10310. On vous demande à nouveau d’estimer comme ci-dessus une valeur approchée du plus grand nombre qu’il soit possible de représenter comme un flottant.
10**300.1e+30010**310.---------------------------------------------------------------------------
OverflowError Traceback (most recent call last)
Cell In[9], line 1
----> 1 10**310.
OverflowError: (34, 'Numerical result out of range')# vos essais successifs iciComplément - niveau avancé¶
En fait, on peut accéder à ces valeurs minimales et maximales pour les flottants comme ceci
import sys
print(sys.float_info)sys.float_info(max=1.7976931348623157e+308, max_exp=1024, max_10_exp=308, min=2.2250738585072014e-308, min_exp=-1021, min_10_exp=-307, dig=15, mant_dig=53, epsilon=2.220446049250313e-16, radix=2, rounds=1)
Et notamment, comme expliqué ici.
print("Flottant minimum", sys.float_info.min)
print("Flottant maximum", sys.float_info.max)Flottant minimum 2.2250738585072014e-308
Flottant maximum 1.7976931348623157e+308
Sauf que vous devez avoir trouvé un maximum voisin de cette valeur, mais le minimum observé expérimentalement ne correspond pas bien à cette valeur.
Pour ceux que cela intéresse, l’explication à cette apparente contradiction réside dans l’utilisation de nombres dénormaux.