Switchelven - Qwice

Ding, ding. C'est l'heure d'une nouvelle anecdote de dev :) Vous vous êtes surement déjà demandé pourquoi il y avait systématiquement une valeur a 3 chiffres sur les bornes de paiemen

Switchelven - Qwice 2024

Ding, ding. C'est l'heure d'une nouvelle anecdote de dev :) Vous vous êtes surement déjà demandé pourquoi il y avait systématiquement une valeur a 3 chiffres sur les bornes de paiement automatiques ou les taux de change ? Une raison connue est la précision, sur une grande quantité, 0.001 centimes sont suffisant pour modifier le total. Mais il y a certainement une autre raison, plus technique. L'enfer des nombres flottants. <p style="text-align:justify;">Il y a 2 ou 3 ans, alors que je travaillais chez TankYou, une société de livraison de carburants, un de mes plus projets a été la création d'un système de facturation automatisé. Nous le mettons en place (on était 2 à l'époque, le lead back plutôt côté front, et moi junior sortant d'école sur le back), on le test en parallèle de la prod, tout va bien. Mise en prod, tout va bien aussi. Plutôt cool jusque la. Au fil des retours clients, nous améliorons le système pour répondre à leurs besoins. Ajout d'un système de regroupement des factures, création d'avoir, mise en place de proto facture, ajout des détails de prix hors taxes avec le pris unitaire, ... Et oups. Problème. Un commercial nous remonte des erreurs sur les détails de factures, plusieurs erreurs...</p><ul><li><p style="text-align:justify;">Le total des lignes hors taxes ne correspond pas au total ht affiché</p></li><li><p style="text-align:justify;">Le total du prix de chaque ligne ne correspond pas à la multiplication entre la quantité et le prix unitaire</p></li></ul><p style="text-align:justify;">Donc, nous commençons les investigations.... Et la, on penses être tombé sur un bug aléatoire (ça existe, promis !). Bon, du coup, on cherche les points communs possible entre les différents cas. Pourquoi certains sont exacte, d'autre non .... On fixe un premier problème: le calcul du total HT n'était pas calculé via la somme des lignes individuelles mais depuis le montant TTC... Car tout était calculé a partir du prix stocké en DB qui est en TTC puis convertis à l'unité au besoin. Ça améliore la situation et du coup, il ne reste plus que le problème de décalage sur les lignes... Et la, pas de pistes. Enfin pas de pistes juqu'à ce qu'on remarque que les problèmes n'ont l'air d'arriver que lorsqu'il y a des quantité différentes de 1... Et que nous nous rappelions d'une petite subtilité des systèmes informatique... Un nombre flottant (un nombre non entier quelconque comme Pi par example) n'est pas stocké exactement.... Autrement dit, si le nombre est attendu comme flottant et que je le déclare comme étant 2.55, la valeur réelle manipulé n'est pas nécessairement exactement 2.55, mais peut être 2.499999999999999989910.... Et quand on se base sur un nombre inexacte, que l'on modifie pour obtenir une base de calcul arrondi a 2 chiffres puis que l'on fait le total, il y a des décalage. Et plus la quantité est importante, plus cette différence est probable et grande. <br /><br />Il n'existe alors que deux solutions.... Tout manipulé dans un nouveau type, le type Décimal qui lui représente les nombre de manière exacte avec la partie entière et la partie décimal, et existe dans la plus part des langage de programmation, si ce n'est tous. Mais ça demande de réécrire une bonne partie du code... C'est long, trop long. Puis une idée issue du constat plus tôt émis: les pompes a essences utilise un prix unitaire a 3 chiffres, et pour des raisons de performance et d'ancienneté, ils n'utilisent probablement pas un type Décimal (plus lourd a manipuler). Et si les 3 chiffres servait a gommer les erreurs de multiplication sur les flottants ? Nous décidons donc de nous basé sur le calcul suivant:<br />- récupérer le prix HT depuis le prix stocké en DB (TTC) arrondie a 3 chiffres (base affiché sur la facture)<br />- calculer le total de la chaque ligne en HT avec une précision de 2 chiffres cette fois<br />- calculer le total HT via la somme des lignes<br />- Appliquer la TVA.<br /><br />Et ho miracle, tout fonctionne parfaitement ! <br /><br />Et voila, fin de l'anecdote. Vous savez désormais a quel points les nombres irrationnel peuvent être irritant, et deux méthodes pour régler le problème :)</p><p style="text-align:justify;"></p><p style="text-align:justify;">(Et pas merci à Thomas pour m'avoir fait tout réécrire du début alors que j'en étais à la moitié ... :p et merci pour ton travail et bonne nuit à toi ;) )<br /></p><p style="text-align:justify;">PS: un test amusant (je ne sais pas si ça le fait encore en python3) pour voir ce problème: afficher tous les entier sous formes décimal (1. 2. 3., etc....) et vous aurez des surprises)</p>

Animation Animation