() => {
Langage

La fourberie des décimaux !

Dans un projet console, amusez-vous à écrire le code suivant :

            Console.WriteLine(Math.Round(2.135, 2));
Console.WriteLine(Math.Round(3.135, 2));

Vous obtiendrez la résultat suivant :

image

Quelle horreur… ! Au delà de ma déception, l’impact peut-être grave dans vos processus métier : facturation, devis, mise sur orbite d’un satellite… 🙂

Microsoft explique ce défaut à cause d’une perte de précision qui résulte de la représentation des valeurs décimales sous la forme de nombres à virgule flottante. L’algorithme interne utiliserais une multiplication qui soufrerais d’une perte de précision.

De ce constant il suffit de ne plus utiliser les méthodes surchargées qui prennent en paramètre les types System.Double, mais d’utiliser celles qui prennent des types System.Decimal comme le code suivant :

            Console.WriteLine(Math.Round(2.135m, 2));
Console.WriteLine(Math.Round(3.135m, 2));

Qui nous donne le résultat souhaité :

image

Notez que je n’utilise pas l’opérateur de casting mais directement une valeur de type System.Decimal. Si vous désirez qu’un littéral soit considéré comme tel, utilisez le suffixe m (ou M), de même que le suffixe d pour un type System.Double, f pour un type System.Float, L pour un type System.Int64 et finalement le préfixe u pour les type non-signés.

Je trouve que la remarque dans la documentation MSDN n’est pas des plus idéale, j’aurais préféré que les surcharges qui prennent en paramètre les types System.Double n’existent tout simplement pas…

Le problème est en fait très complexe, même si l’on ne s’en rend pas compte, traiter des nombres décimaux par des ordinateurs a toujours été une prouesse, surtout lorsqu’un nombre a une infinité de décimaux, c’est comme demander à un humain d’écrire le nombre π, ou même 1/3, c’est aussi compliqué que çà !

L’exemple par la preuve :

            Console.WriteLine(1 / 9m * 9m);

Donne le résultat suivant :

image

Que le code suivant corrige :

            Math.Round(1 / 9m * 9m, 0);

Pourtant la même opération avec des types System.Double donne directement le bon résultat (1) !!!

            Console.WriteLine(1 / 9d * 9d);

En réalité tout dépend de la représentation en mémoire de la valeur et de la perte de précision de l’opération. Retenons simplement que lorsque nous devrons gérer des nombres décimaux, nous resterons vigilant car il n’y a rien de si naturel à cela !

Publicités

À propos de vpetetin

Lorsqu’en 1989 j'écris ma première ligne de code, c’est sans me rendre compte que j'avais été frappé par la foudre du dieu logiciel ! Séduit par les technologies Microsoft, j'ai débuté ma carrière en C avec les joies des interfaces MFC et objets COM. Toujours à la recherche d’industrialisation et de réutilisabilité, après plus de 12 ans d'expériences, je continue aujourd’hui ma carrière en tant qu’architecte consultant .NET et donne régulièrement des formations tout en m’orientiant vers la plateforme Windows Azure. Eternel enthousiaste, je ne manquerai jamais d’aborder avec vous les sujets de nos vies quotidiennes avec bonne humeur et philosophie.

Discussion

4 réflexions sur “La fourberie des décimaux !

  1. oh branleur ! ca post pas des masses 🙂

    Publié par Jean-Rémi Pinna | 11 août 2015, 15:39
  2. Vincent il a raison, ça bosse pas des masses ici!!!!
    Je t’ai connu plus inspiré

    Publié par amethyste16 | 5 octobre 2015, 21:18
  3. Si tu savais mon vieil ami, à nous deux on fabriquerait un .NET9, tous « neuf » et sans bavure…

    Perso, pas le temps de bloguer, et j’en suis le premier fautif je le sais ! Mais que Veux-tu, dès que j’en apprends plus, au lieu de partager je passe à l’étape suivante pour faire des projets perso. Celui du moment est une application sur le projet open-source domoticz.

    C’est vrai que c’est dommage car je pourrais en dire des masses et le « welcome » de mon blog ne prétendait pas à si peu de contenu, mais je préfère m’épanouir comme çà ; pour le moment en tous les cas !

    Je suis content que de ton côté, tu es repris ton blog, qui est aussi pragmatique que de bonne qualité !

    Au plaisir Monsieur le chimiste 😉

    Publié par vpetetin | 5 octobre 2015, 23:29

Répondre à Jean-Rémi Pinna Annuler la réponse.

Choisissez une méthode de connexion pour poster votre commentaire:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s

Catégories

Mises à jour Twitter

Entrez votre adresse email pour suivre ce blog et recevoir les notifications de nouveaux messages par email.

Rejoignez 3 autres abonnés

%d blogueurs aiment cette page :