CodeGym /Cours /C# SELF /Problèmes de précision et valeurs spéciales

Problèmes de précision et valeurs spéciales

C# SELF
Niveau 6 , Leçon 3
Disponible

1. Introduction

On pourrait croire que si un ordi est "intelligent", alors 0.1 + 0.2 devrait juste donner 0.3. Mais en vrai, c’est pas si simple. On va voir ça sur un exemple tout bête.

double x = 0.1;
double y = 0.2;
double sum = x + y;
Console.WriteLine(sum); // Qu’est-ce que le programme va afficher ?
Addition de nombres à virgule flottante : on attend 0.3, mais qu’est-ce qu’on a vraiment ?

Et maintenant, essaye de comparer avec 0.3 :

Console.WriteLine(sum == 0.3); // Ici, ça va être true ou false ?

Si tu vois False, t’étonne pas !

La raison est dans la représentation des nombres en mémoire

Les ordis bossent avec les nombres en binaire. Mais toutes les fractions décimales ne peuvent pas être représentées exactement en binaire, comme 1/3 qu’on ne peut pas écrire exactement en décimal (0.333...). Par exemple, 0.1 en binaire — c’est une fraction infinie, donc on doit "arrondir" pour la stocker.

Pour le dire simplement, double fait parfois "comme si" il stockait ton nombre pile-poil, mais en vrai il garde juste une valeur très proche.

2. Quels "bugs" on peut avoir avec l’arithmétique double ?

Voyons des exemples concrets.

Exemple 1. La fameuse "magie" de 0.1 + 0.2

double a = 0.1;
double b = 0.2;
double sum = a + b;
Console.WriteLine(sum);            // 0.30000000000000004
Console.WriteLine(sum == 0.3);     // False

L’ordi affiche pas 0.3, mais 0.30000000000000004. La différence est minuscule, mais si tu bosses, par exemple, dans la finance — ça devient grave.

Exemple 2. Addition itérative

double result = 0;
for (int i = 0; i < 10; i++)
{
    result += 0.1;
}
Console.WriteLine(result); // 0.9999999999999999

Tu voulais 1.0 — t’as eu un peu moins. Encore une fois, c’est à cause de l’arrondi à l’intérieur du double.

Pourquoi c’est important dans la vraie vie

Beaucoup se disent : "On s’en fout, c’est qu’une petite erreur, pas grave !" Regardons un exemple du monde des paiements.

Imaginons que ta banque en ligne additionne 100 transactions de 0.1 euro. Si ton programme "perd" un cent-millième d’euro à chaque itération, à l’échelle de la banque tu vas "perdre" de l’argent réel. Et là, le comptable va débarquer direct et demander : "Où est passé notre argent ?!"

3. Comment comparer correctement les nombres à virgule flottante

Comme double ne peut souvent pas stocker exactement la valeur que tu veux, comparer directement avec == peut te jouer des tours. À la place, on compare en général la valeur absolue de la différence avec un tout petit nombre (epsilon).

Exemple de comparaison avec une tolérance

double a = 0.1 + 0.2;
double b = 0.3;
double epsilon = 0.000001;

if (Math.Abs(a - b) < epsilon)
{
    Console.WriteLine("Presque égal !"); // C’est plus sûr de comparer comme ça
}

Ici on dit : "Si la différence entre les nombres est plus petite qu’un millionième, on considère qu’ils sont égaux".

4. Valeurs spéciales de double : Infinity, NaN, -Infinity

Le type double stocke pas que des nombres, mais aussi des valeurs spéciales. Elles apparaissent dans des situations que même un prof de maths interdirait à ses élèves.

L’infini (Infinity)

Qu’est-ce qui se passe si tu divises 1 par 0 ?

double result = 1.0 / 0.0;
Console.WriteLine(result); // Infinity

En C# (et dans plein de langages), diviser par 0 pour un double ne lance pas d’exception ! À la place, le résultat devient une valeur spéciale "infini positif".

Moins l’infini (-Infinity)

Si tu divises un nombre négatif par 0, tu obtiens l’infini négatif :

double result = -1.0 / 0.0;
Console.WriteLine(result); // -Infinity

"Pas un nombre" (NaN — Not a Number)

Si tu fais un truc vraiment bizarre, genre essayer de calculer la racine carrée d’un nombre négatif :

double result = Math.Sqrt(-1);
Console.WriteLine(result); // NaN

Ou le résultat de 0.0 / 0.0 :

double result = 0.0 / 0.0;
Console.WriteLine(result); // NaN

NaN — c’est "tout ce qui ne serait pas un nombre dans la vraie vie".

Vérifier les valeurs spéciales

En C#, t’as des fonctions pour checker les valeurs spéciales :

Console.WriteLine(double.IsInfinity(result));    // true si c’est l’infini
Console.WriteLine(double.IsNaN(result));         // true si c’est NaN

Tableau : Comment double réagit aux opérations bizarres

Opération Résultat Ce qui est stocké dans double
1.0 / 0.0
Infinity +∞
-1.0 / 0.0
-Infinity -∞
0.0 / 0.0
NaN Pas un nombre
Math.Sqrt(-1)
NaN Pas un nombre
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION