Le milieu qui déborde
Exercice · niveau 2 · informatique (MP2I/MPI), chapitre 3 — Algorithmes, programmes et complexité
Énoncé
Le chapitre affirme que (g + d) / 2 peut déborder là où g + (d - g) / 2 ne le fait pas. Le vérifier, et expliquer pourquoi la seconde forme est sûre.
Corrigé
Avec int g = 2000000000; et int d = 2100000000;, les deux formes sont mesurées :
INT_MAX = 2147483647
g + d (en long) = 4100000000 (au-dela de INT_MAX)
(g + d) / 2 = -97483648 <-- NEGATIF
g + (d - g) / 2 = 2050000000 correct
Le résultat n'a rien d'aléatoire : , et la division par deux donne . C'est le dépassement en complément à deux du chapitre chap:langage-c, à un endroit où personne ne le cherche. Employé comme indice, ce nombre sort du tableau, et le langage ne le vérifie pas.
Pourquoi la seconde forme est sûre. Si , alors est compris entre et , donc tient. Sa moitié aussi. Et , qui tient par hypothèse. Aucune valeur intermédiaire ne dépasse : c'est la propriété qu'il faut savoir énoncer, et elle se démontre en une ligne.
La forme générale de la parade. On l'a déjà vue à l'exercice 1.2 : pour tester sans déborder, on écrit . Ici, pour calculer une moyenne sans déborder, on calcule un écart puis on l'ajoute. Dans les deux cas, la règle est la même : réorganiser l'expression pour qu'aucun calcul intermédiaire ne sorte de l'intervalle des données.
Ce défaut a vécu neuf ans dans la recherche dichotomique de la bibliothèque standard de Java. Il n'apparaît que sur des tableaux de plus d'un milliard de cases — c'est-à-dire jamais, jusqu'au jour où si. Aucun jeu de tests raisonnable ne l'attrape : c'est un cas où seule la relecture de l'expression, ou une preuve, protège. Le chapitre chap:discipline y revient.
Les autres exercices de ce chapitre Le cours du chapitre
Un blocage sur cet exercice ? Le tuteur d'Adloun guide par questions, sans donner la réponse.