Ordinateur, fais moi une addition

Parfois, les limitations de l’ordinateur se font sentir. Exemple à la con:
Je fais une somme sur une liste de nombres réels. Suivant l’ordre dans lequel l’ordinateur additionne les nombres, il donne un résultat « légèrement » différent.

#!/usr/bin/python
values = [76923076923, 1428.5714285714284, 1250000.0, 8333.333333333332, 125000000.0, 7142857.142857143]
sorted_values = sorted(values)
print "sum", sum(values)
print "sum sorted", sum(sorted_values)
print "equality", sum(values) == sum(sorted_values)
print "difference", sum(sorted_values) - sum(values)

sum 77056479542.0
sum sorted 77056479542.0
equality False
difference 1.52587890625e-05

C’est bien sûr du à la manière dont sont stockés et manipulés les nombres réels sur un ordinateur. Ici, en nombre à virgule flottante sur 64bits. Le problème se reproduit dans d’autres langages.

C’est plutôt gênant quand on fait du multithreading car on s’attend à ce que l’addition de données en provenance désordonnée de plusieurs threads donne la même chose que l’addition de données provenant d’un seul thread. Mais non, il faut prendre ses précautions.

6 réactions sur “ Ordinateur, fais moi une addition ”

  1. sky

    Suffit de prendre un bon langage, comme Perl6 :-D

    « `
    #!/usr/bin/env perl6
    my @values = 76923076923, 1428.5714285714284, 1250000.0, 8333.333333333332, 125000000.0, 7142857.142857143;
    my @sorted_values = @values.sort;
    my ($sum, $sum_sorted) = (0, 0);
    for @values -> $num {
    $sum += $num;
    }
    for @sorted_values -> $num {
    $sum_sorted += $num;
    }
    say « sum  » ~ $sum;
    say « sum sorted  » ~ $sum_sorted;
    say « equality  » ~ ($sum == $sum_sorted);
    say « difference  » ~ ($sum_sorted – $sum);
    « `

    La sortie :
    « `
    sum 77056479542.0476190477604
    sum sorted 77056479542.0476190477604
    equality True
    difference 0
    « `

    Enjoy :-)

  2. Tuxicoman

    D’ailleurs, les modules comme Decimal en Python, ils sont implémentés comment? Avec des entiers? Je suppose que la performance en prend un coup?

  3. Tuxicoman

    même avec le module Decimal:
    Decimal(« 1 ») / Decimal(« 3 ») * Decimal(« 3 ») != Decimal(« 1 »)

    Qu’en dit perl6 ?

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.