Adloun

Hors programme. La sommation de Kahan corrige l'accumulation d'erreurs…

Exercice supplémentaire · niveau 3 (difficile) · NSI (première), chapitre 2 — Flottants, booléens et textes · Sous le capot des flottants

Énoncé

Hors programme. La sommation de Kahan corrige l'accumulation d'erreurs en mémorisant, à chaque tour, ce que l'addition vient de perdre. L'implémenter, la comparer à la somme naïve sur [0.1] * 1000, et expliquer la ligne c = (u - s) - y.

Corrigé


def somme_kahan(t):
    """Somme compensee : c retient ce que l'addition a perdu.

    Invariant : a chaque tour, s + (-c) approche la somme exacte des
    elements deja traites, bien mieux que s seul.
    """
    s = 0.0
    c = 0.0
    for x in t:
        y = x - c          # on reinjecte l'erreur du tour precedent
        u = s + y          # addition arrondie
        c = (u - s) - y    # ce que l'arrondi a mange
        s = u
    return s

>>> t = [0.1] * 1000
>>> somme_naive(t)
99.9999999999986
>>> somme_kahan(t)
100.0
>>> abs(somme_naive(t) - 100.0)
1.4068746168049984e-12
>>> abs(somme_kahan(t) - 100.0)
0.0

La ligne magique. En arithmétique exacte, : la ligne serait inutile. En flottants, n'est pas mais son arrondi ; rend donc la part de qui a réellement été ajoutée, et lui retirer donne exactement la part perdue. On la retranche au tour suivant : rien ne se perd deux fois.

Ce que l'exercice enseigne. Une identité algébrique vraie sur peut être fausse sur les flottants — et ici, c'est cette fausseté même qui est exploitée. Un compilateur trop zélé qui « simplifierait » cette ligne en casserait l'algorithme ; c'est une des raisons pour lesquelles les optimisations flottantes agressives sont désactivées par défaut.

Prolongement : math.fsum va plus loin encore et garantit le résultat correctement arrondi, c'est-à-dire le flottant le plus proche de la somme exacte. Dans un vrai programme, on l'utilise plutôt que de réécrire Kahan.

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.