Adloun

informatique (MP2I/MPI) · Chapitre 3 · Application directe du cours

Problème — Sommer un million de termes, et l'ordre qui change tout

Algorithmes, programmes et complexité · niveau 3 (difficile)

Énoncé

On calcule pour , en float (32 bits, bits de mantisse).

  • Sommer dans l'ordre croissant des , puis dans l'ordre décroissant. Comparer à la valeur exacte.
  • Expliquer l'écart.
  • À partir de quel rang l'ajout de ne change-t-il plus rien ?
  • Quelle règle générale en tirer ?

Corrigé

1. Les deux sommes, mesurées.


n = 10 000 000
float, k croissant   : 15,403682709
float, k decroissant : 16,686031342
double (reference)   : 16,695311366
ln(n) + gamma        : 16,695311316      (valeur theorique)

erreur, ordre croissant   : 1,291628657
erreur, ordre decroissant : 0,009280024

Le même calcul, les mêmes additions, les mêmes termes : deux résultats qui diffèrent de , soit près de . Et l'ordre décroissant est fois plus précis que l'ordre croissant.

La colonne de référence n'est pas une commodité : la somme en double coïncide avec sur sept décimales, où est la constante d'Euler. C'est ce qui autorise à parler d'« erreur » pour les deux autres.

2. L'explication : l'absorption. Dans l'ordre croissant, la somme partielle atteint vite une taille de l'ordre de , tandis que les termes deviennent minuscules. Or un float ne porte que bits de mantisse : à côté d'un total , l'écart entre deux flottants consécutifs vaut environ . Tout terme inférieur à la moitié de cet écart est purement et simplement absorbé : rend .

Dans l'ordre décroissant, les petits termes sont additionnés entre eux d'abord, quand le total est encore petit. Ils s'accumulent au lieu de disparaître, et ne rejoignent le gros total qu'une fois devenus significatifs.

3. Le rang d'absorption, mesuré :


premier k tel que s + 1/k == s (en float) : 2097152

Et , exactement la valeur prédite par le raisonnement ci-dessus ( équivaut à ). Sur les termes, près de millions n'ont donc contribué à rien du tout dans la version croissante — le programme a passé la majeure partie de son temps à ajouter zéro.

4. La règle. Quand on somme des termes de tailles très différentes, on commence par les plus petits. Plus généralement :

  • on n'additionne pas un petit nombre à un grand si on peut l'éviter ;
  • on préfère un double à un float dès qu'on somme beaucoup de termes — la même expérience en double donne les deux ordres identiques sur neuf décimales ;
  • et l'on garde à l'esprit que deux programmes mathématiquement équivalents ne le sont pas numériquement. C'est la conséquence de la perte d'associativité mesurée à l'exercice 3.6.
AttentionCe que cela implique pour le calcul parallèle

Répartir une somme sur plusieurs c{œ}urs change l'ordre des additions, donc le résultat. Un programme parallèle correct peut donc rendre deux valeurs différentes sur deux exécutions, sans qu'aucun défaut n'existe. Le chapitre chap:concurrence le rencontre pour d'autres raisons ; celle-ci est purement numérique, et elle interdit de tester un calcul flottant par une égalité exacte avec une exécution de référence.

Exercices semblables

Le cours du chapitre · Tous les exercices du chapitre