Si je vous demande, combien font 0,1 + 0,2 ? Vous pouvez me jeter un regard vide, 0,1 + 0,2 = 0,3 Ah, avez-vous encore besoin de demander ? Même les enfants de la maternelle peuvent répondre à une telle question pédiatrique. Mais vous savez, le même problème dans un langage de programmation n’est peut-être pas aussi simple qu’on l’imagine.
Vous n'y croyez pas ? Regardons d'abord un morceau de JS.
var numA = 0,1 ;
var numB = 0,2 ;
alerte( (numA + numB) === 0,3 );
Le résultat de l'exécution est faux. Oui, quand j'ai vu ce code pour la première fois, j'ai pris pour acquis qu'il était vrai, mais les résultats de l'exécution m'ont surpris. Ma méthode d'ouverture est-elle erronée ? Non, non. Essayons d'exécuter à nouveau le code suivant et nous saurons pourquoi le résultat est faux.
var numA = 0,1 ;
var numB = 0,2 ;
alerte (numA + numB);
Il s'avère que 0,1 + 0,2 = 0,30000000000000004. N'est-ce pas bizarre ? En fait, pour les quatre opérations arithmétiques sur les nombres à virgule flottante, presque tous les langages de programmation auront des problèmes similaires aux erreurs de précision. Cependant, dans des langages tels que C++/C#/Java, les méthodes ont été encapsulées pour éviter les problèmes de précision, et JavaScript est un type faible. Le langage n'a pas de type de données strict pour les nombres à virgule flottante du concept de conception, le problème de l'erreur de précision est donc particulièrement important. Analysons pourquoi il y a cette erreur de précision et comment y remédier.
Tout d’abord, nous devons réfléchir au problème apparemment pédiatrique de 0,1 + 0,2 d’un point de vue informatique. Nous savons que ce qui peut être lu par les ordinateurs est binaire et non décimal, alors convertissons d'abord 0,1 et 0,2 en binaire et jetons un œil :
0,1 => 0,0001 1001 1001 1001… (boucle infinie)
0,2 => 0,0011 0011 0011 0011… (boucle infinie)
La partie décimale d'un nombre à virgule flottante double précision prend en charge jusqu'à 52 bits, donc après avoir ajouté les deux, nous obtenons une chaîne de 0,0100110011001100110011001100110011001100110011001100. Le nombre binaire est tronqué en raison de la limitation des décimales des nombres à virgule flottante. À ce stade, nous le convertissons en décimal et il devient 0,30000000000000004.
Alors voilà, comment résoudre ce problème ? Le résultat que je veux est 0,1 + 0,2 === 0,3 Ah ! ! !
L'une des solutions les plus simples consiste à donner des exigences de précision claires lors du processus de renvoi de la valeur, l'ordinateur arrondira automatiquement, telles que :
var numA = 0,1 ;
var numB = 0,2 ;
alert( parseFloat((numA + numB).toFixed(2)) === 0.3 );
Mais évidemment, ce n’est pas une méthode unique. Ce serait formidable s’il existait une méthode qui pourrait nous aider à résoudre le problème de précision de ces nombres à virgule flottante. Essayons cette méthode :
Math.formatFloat = fonction (f, chiffre) {
var m = Math.pow(10, chiffre);
return parseInt(f * m, 10) / m;
}
var numA = 0,1 ;
var numB = 0,2 ;
alert(Math.formatFloat(numA + numB, 1) === 0,3);
Que signifie cette méthode ? Afin d'éviter les différences de précision, nous devons multiplier le nombre à calculer par 10 à la puissance n, le convertir en un entier que l'ordinateur peut reconnaître avec précision, puis le diviser par 10 à la puissance n. Les langages de programmation gèrent les différences de précision, nous l'utiliserons pour gérer l'erreur de précision des nombres à virgule flottante dans JS.
Si quelqu’un vous demande la prochaine fois à quoi équivaut 0,1 + 0,2, vous devez être prudent dans votre réponse ! !