Si vous faites de la programmation, vous avez peut-être entendu dire que "les nombres à virgule flottante ont une erreur".
Mais en êtes-vous toujours conscient? Je n'étais pas au courant et je l'ai vécu.
Un jour, j'ai dû gagner 0,5% d'intérêt sur le solde de dépôt d'un utilisateur, arrondi au nombre entier inférieur le plus proche. J'ai écrit ce code parce que je pensais que c'était un simple calcul.
JavaScript
Math.floor(value * 1.005)
…… ** C'est une erreur. ** **
Essayons de mettre «1000» en «valeur». J'ai envie d'ajouter 0,5% à 1000 donne 1005, mais en réalité cela devient 1004. L'exemple ci-dessus est JavaScript, mais dans la plupart des langues principales, le résultat est le même. Essayons-le à portée de main.
Pourquoi cela arrive-t-il? Si vous essayez de sortir "1000 * 1.005" tel quel, ce sera "1004.9999999999999". Cette valeur n'a tout simplement pas atteint 1005, donc si vous la tronquez, elle sera 1004. Les nombres à virgule flottante ne peuvent pas représenter avec précision 1,005, il semble donc qu'une erreur s'est produite.
Cette erreur est vraiment facile à se produire. Tous les exemples suivants ne produisent pas les résultats attendus.
JavaScript
Math.floor(0.6 / 0.2) // 2
0.6 / 0.2 // 2.9999999999999996
JavaScript
//Taxe à la consommation arrondie au nombre entier supérieur le plus proche
Math.ceil(900 * 1.08) // 973
900 * 1.08 // 972.0000000000001
JavaScript
let f = 0;
for (let i = 0; i < 10; i++) {
f += 0.1;
}
Math.floor(f) // 0
f // 0.9999999999999999
Il vaut mieux penser que le résultat du calcul d'un nombre à virgule flottante ne sera pas un entier.
Vous pouvez éviter ce problème en arrondissant les résultats à un chiffre suffisamment bas avant de les arrondir.
JavaScript
//Arrondi au 4e chiffre
Math.floor((value * 1.005).toFixed(3))
Java
Math.floor(String.format("%.3f", value * 1.005))
PHP
floor(round($value * 1.005, 3))
Il peut ne pas convenir aux situations où des calculs rigoureux sont nécessaires, mais pour la plupart des applications, cela devrait être suffisant. Vous souhaiterez peut-être étendre la classe Math afin qu'elle puisse être appelée à partir de l'ensemble de l'application.
J'ai reçu un commentaire. En utilisant le type Decimal, il est possible d'effectuer des calculs sans erreur sans aucune implémentation étrange. Les classes BigDecimal peuvent être utilisées en standard en Java, et JavaScript possède également une bibliothèque appelée decimal.js. Il vaut mieux utiliser quelque chose comme ça que de l'implémenter vous-même. (Ajout jusqu'à présent)
Soyez prudent lors du calcul des fractions.
Recommended Posts