6 votes

Javascript se multiplie de manière incorrecte, ce qui entraîne un arrondi incorrect

Lorsque je tire les valeurs que je veux multiplier, ce sont des chaînes de caractères. Je les extrais donc, les analyse en tant que flottants (pour préserver les décimales) et les multiplie ensemble.

LineTaxRate = parseFloat(myRate) * parseFloat(myQuantity) * parseFloat(myTaxRateRound);

Cela a fonctionné pour 99 % de mes factures, mais j'ai découvert un problème très étrange.

Quand il s'est multiplié : 78 * 7 * 0.0725

Javascript est de retour : 39.584999999999994

Lorsque vous faites normalement le calcul avec une calculatrice, son.. : 39.585

Quand tout est dit et fait, je prends ce chiffre et je l'arrondis en utilisant les chiffres suivants .toFixed(2)

Parce que Javascript renvoie ce nombre, il n'arrondit pas à la valeur désirée de : $39.59

J'ai essayé Math.round() le total mais j'obtiens toujours le même chiffre.

J'ai pensé à arrondir le nombre à trois décimales puis à deux, mais cela me semble peu pratique.

J'ai cherché partout et tout ce que je vois, c'est que les gens mentionnent que parseFloat perd sa précision, et qu'il faut utiliser .toFixed, mais dans l'exemple ci-dessus, cela n'aide pas.

Voici mon test script que j'ai fait pour recréer le problème :

<script>
var num1 = parseFloat("78");
var num2 = parseFloat("7");
var num3 = parseFloat("0.0725");
var myTotal = num1 * num2 * num3;
var result = Math.round(myTotal*100)/100

alert(myTotal);
alert(myTotal.toFixed(2));
alert(result);
</script>

6voto

krasnerocalypse Points 580

Les points flottants sont représentés en binaire, et non en décimal. Certains nombres décimaux ne seront pas représentés avec précision. Et malheureusement, comme Javascript ne dispose que d'une seule classe Number, ce n'est pas un très bon outil pour ce travail. D'autres langages disposent de bibliothèques décimales décentes conçues pour éviter précisément ce type d'erreur. Vous allez devoir soit accepter des erreurs d'un centime, soit implémenter une solution côté serveur, soit travailler très dur pour résoudre ce problème.

edit : ooh ! vous pouvez faire 78 * 7 * 725 et ensuite diviser par 10000, ou pour être encore plus précis il suffit de mettre le point décimal au bon endroit. En gros, représenter le taux d'imposition comme autre chose qu'une minuscule fraction. C'est moins pratique, mais cela évitera probablement vos erreurs de multiplication.

1voto

Yashua Points 3482

Vous pourriez trouver le Comptabilité.js bibliothèque utile pour cela. Elle dispose d'une méthode toFixed() "améliorée".

0voto

Devid Points 767

JavaScript/TypeScript n'ont qu'une seule classe Number, ce qui n'est pas très bon. J'ai le même problème car j'utilise TypeScript. J'ai résolu mon problème en utilisant decimal.js-light bibliothèque.

new Decimal(78).mul(7).mul(0.0725) returns as expected 39.585

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X