TP: Implanter la fonction exponentielle (3/5)¶
Partie 3 : Comparaison de nombres flottants et précision relative¶
Sur les nombres flottants (float
ou double
) l’opérateur ==
n’est pas toujours très fiable à cause des erreurs d’arrondis:
1.0 + 1e20 - 1e20 == 1e20 - 1e20 + 1.0
Exécutez les 5 cellules suivantes. Que constatez-vous ?
BEGIN SOLUTION
a
et b
ont bien des valeurs différentes mais s’affichent de la même manière.
END SOLUTION
double a,b;
a = 16;
b = 15.99999999999;
a
b
(a == b)
Définition: précision relative¶
Aussi, chaque fois que l’on veut comparer deux nombres flottants, il faut spécifier avec quelle précision on veut les comparer. Comme on manipule certaines fois des nombres très grands et d’autres fois des nombres très petits, ce qui compte c’est la précision relative: le nombre de chiffres significatifs en communs.
Par exemple, si on veut comparer \(x\) et \(y\) avec une précision relative de cinq chiffres significatifs, on prendra \(\varepsilon=10^{-5}=0,00001\), et on dira que \(x\) est égal à \(y\) à \(\varepsilon\) près si:
Moralement: la différence entre \(x\) et \(y\) est négligeable devant \(x\) et devant \(y\).
Implantation¶
Implantez les deux fonctions suivantes dont on vous donne la documentation :
abs
mais qui prend cette fois en paramètre undouble
et retourne undouble
egal
qui prend en paramètre les nombres \(x\), \(y\) et \(\varepsilon\).
/** Valeur absolue pour type double
* @param x un nombre de type double
* @return la valeur absolue de x
**/
/// BEGIN SOLUTION
double abs(double x) {
if (x < 0) {
return -x;
} else {
return x;
}
}
/// END SOLUTION
abs(-1.5)
CHECK( abs(-1.5) == 1.5 );
CHECK( abs( 2.2) == 2.2 );
/** Égalité entre deux flottants avec précision relative
* @param x un nombre de type double
* @param y un nombre de type double
* @param epsilon un nombre de type double
* @return true si la valeur absolue de x - y est plus petite que epsilon * |x| et que epsilon * |y|
**/
/// BEGIN SOLUTION
bool egal(double x, double y, double epsilon) {
double v = abs(x-y);
return ((v < epsilon * abs(x)) and (v < epsilon * abs(y)));
}
/// END SOLUTION
egal(15.999999, 16,0.00001)
CHECK( egal(15.999999, 16, 0.00001) == true );
CHECK( egal(15.99, 16, 0.00001) == false );
Trouvez des valeurs de epsilon
telles que les nombres ci-dessous soient considérés comme égaux par egal
:
egal(15, 16, 0.001)
egal(0.0001, 0.002, 0.00001)
Que se passe-t-il lorsque \(x\) ou \(y\) valent 0 ?
BEGIN SOLUTION
Lorsque \(x\) ou \(y\) valent 0 (même lorsque les deux valent 0), la fonction egal
retourne toujours false
. On ne peux pas parler de précision relative à zéro.
END SOLUTION
egal(0.00001, 0, 0.0000001)