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 ?
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 |
|---|---|---|
|
Infinity | +∞ |
|
-Infinity | -∞ |
|
NaN | Pas un nombre |
|
NaN | Pas un nombre |
GO TO FULL VERSION