BTS SIO - Notes de cours

Accueil > Première année > SI4-SI6 > Erreurs d’arrondi dans les calculs en virgule flottante

Erreurs d’arrondi dans les calculs en virgule flottante

vendredi 6 décembre 2013, par

Les nombres réels sont stockés dans les programmes sous formes de nombres « à virgule flottante », composés d’une mantisse et d’un exposant.

Dans certain cas, surtout lorsqu’on fait des soustractions sur des nombres très proches, de grosses erreurs d’arrondis apparaissent (cela s’appelle la cancellation). Il faut donc être très prudent dans l’utilisation des réels et préférer les entiers autant que possible.

Voici un exemple. Les deux nombres réels, très grands, r et s, sont différent de 100. À leur échelle, c’est une très petite différence. On fait le calcul de (r-s)*r-(r*r-r*s). Mathématiquement, il est facile de se rendre compte que c’est égal à zéro. Pourtant, le résultat obtenu est très loin de zéro, très loin de la précision de la mantisse, très proche des valeurs de r et s. L’erreur est énorme.

Pour se convaincre, on effectue le même calcul en utilisant des entiers longs, R et S. On se rend compte que le résultat obtenu est bien zéro, sans erreur.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Les réels sont en double précision, sur 64bits
# 12bits d'exposant 52bits de mantisse qui déterminent la précision.
# La différence entre r et s se situe à la 14ème décimale de la mantisse
r=3.1415978954126897e+16
s=3.1415978954126797e+16
# r et s sont des réels, R et S sont des entiers longs. r=R et s=S
R=31415978954126897
S=31415978954126797
Q=long(r)
# Déjà, on peut se rendre compte que le nombre stocké est plus petit que r, de1. C'est une très petite erreur.
print("Erreur d'arrondi intiale : "+str(R-Q)+" Soit une erreur relative de "+str((R-Q)/r))
print("Mise en évidence des erreurs d'arrondis dans les calculs en virgule flottante (cancellation)")
d=(r-s)*r
c=r*r-s*r
print("Résultats du calcul de (r-s)*r : "+str(d)+" \nRésultat du calcul de r*r-r*s : "+str(c))
print("Résultat du calcul de (r-s)*r-(r*r-s*r) : "+str(d-c))
print("L'erreur d'arondi relative du calcul de (r-s)*r par rapport au calcul de r*r-r*s est de "+str((d-c)/d)+". Soit une erreur de "+str(int(10000*(d-c)/d)/100.0)+"%")
print("")
print("Calcul sur les entiers")
D=(R-S)*R
C=R*R-S*R
print("Résultats du calcul de (r-s)*r : "+str(C)+" \nRésultat du calcul de r*r-r*s : "+str(D))
print("Calcul de la différence (r-s)*r-(r*r-s*r) : "+str(D-C))

Voici l’exécution du programme :

Erreur d'arrondi intiale : 1 Soit une erreur relative de 3.18309355077e-17
Mise en évidence des erreurs d'arrondis dans les calculs en virgule flottante (cancellation)
Résultats du calcul de (r-s)*r : 3.14159789541e+18
Résultat du calcul de r*r-r*s : 3.02641894959e+18
Résultat du calcul de (r-s)*r-(r*r-s*r) : 1.1517894582e+17
L'erreur d'arondi relative du calcul de (r-s)*r par rapport au calcul de r*r-r*s est de 0.0366625359623. Soit une erreur de 3.66%

Calcul sur les entiers
Résultats du calcul de (r-s)*r : 3141597895412689700
Résultat du calcul de r*r-r*s : 3141597895412689700
Calcul de la différence (r-s)*r-(r*r-s*r) : 0

Un message, un commentaire ?

Qui êtes-vous ?
Votre message

Pour créer des paragraphes, laissez simplement des lignes vides.