Accueil > Articles > Comparaison de deux nombres décimaux

Comparaison de deux nombres décimaux

Voici un problème que j’ai rencontré récemment. Le but est d’écrire un petit test qui permet de déclencher une alerte si la différence entre deux nombres décimaux (par exemple des prix) dépasse un certain seuil. Le test est donc très simple, il s’agit juste de vérifier | a – b | > c :

double a = 0.06;
double b = 0.05;
double c = 0.01;
Console.WriteLine(Math.Abs(a - b) > c);

La différence entre les deux nombres est de 0.01, ce qui n’est pas strictement supérieur à la valeur de c, donc le test renvoie bien False comme prévu. Jusqu’ici, tout va bien.

Pour simplifier, on écrira juste :

Console.WriteLine(Math.Abs(0.06 - 0.05) > 0.01);
→ False

 

On change ensuite les valeurs pour un nouveau test (les nombres ici sont toujours considérés comme de type double) :

Console.WriteLine(Math.Abs(1.06 - 1.05) > 0.01);
→ True

La différence entre les deux nombres est toujours de 0.01, mais cette fois le test renvoie True, ce qui ne correspond pas au résultat attendu.

En regardant plus en détails au cours de l’exécution, le résultat de la soustraction de 1.06 par 1.05 donne en fait 0.010000000000000009, ce qui est supérieur à 0.01. Le problème vient en fait de la façon dont les nombres sont mémorisés avec les types float et double (types de stockage numériques à virgule flottante), ce qui peut engendrer des résultats surprenants lors des calculs.

Pour contourner cette limitation, plusieurs solutions sont possibles. Une des plus simples consiste à effectuer la soustraction avec des nombres de type decimal au lieu des types double ou float. Ce format permet de stocker la partie décimale de façon exacte, ce qui permet d’effectuer des calculs beaucoup plus précis (et justes) :

Console.WriteLine((double)Math.Abs((decimal)1.06 - (decimal)1.05) > 0.01);
→ False

 

Attention : Le type de donnée decimal possède une plus grande précision que les types double ou float, mais sa plage de valeurs est plus étroite (le tableau de comparaison est disponible sur le mémo). Il est donc possible que la conversion déclenche une erreur de dépassement de capacité pour les très grandes valeurs.

Plus d’infos sur le type decimal sont disponibles sur MSDN.

 

  1. Pas encore de commentaire
  1. Pas encore de trackbacks