2010-08-09 26 views
32

Possible en double:
Is JavaScript’s Math broken?Pourquoi l'ajout de deux décimales dans Javascript produit-il un mauvais résultat?

Pourquoi JS bousiller ce simple calcul?

document.write(.1 + .2) // 0.3000000000000004 
document.write(.3 + .6) // 0.8999999999999999 

Le premier exemple est supérieur au résultat correct, tandis que le second est inférieur. ??? !! Comment réparez-vous ceci? Devez-vous toujours convertir des nombres décimaux en entiers avant d'effectuer des opérations? Dois-je seulement m'inquiéter d'ajouter (* et/ne semble pas avoir le même problème dans mes tests)?

J'ai regardé dans beaucoup d'endroits pour des réponses. Certains tutoriels (comme les formulaires de panier) prétendent que le problème n'existe pas et ajoutent simplement des valeurs ensemble. Les gourous fournissent des routines complexes pour diverses fonctions mathématiques ou mentionnent que JS «fait un mauvais travail» en passant, mais je n'ai pas encore vu d'explication.

+0

Vérifiez les réponses à cette question: http://stackoverflow.com/questions/588004/is-javascripts-math-broken –

+0

Possible duplication de milliers de question de ce forum et de chaque forum lié à la programmation là-bas. –

+0

Encore une fois ?! Nous avons vraiment besoin d'écrire une FAQ. –

Répondre

6

Ceci n'est pas une limitation de javascript uniquement, elle s'applique à tous les calculs à virgule flottante. Le problème est que 0,1 et 0,2 et 0,3 ne sont pas exactement représentables en tant que flottants javascript (ou C ou Java, etc.). Ainsi, la sortie que vous voyez est due à cette imprécision.

En particulier, seules certaines sommes de puissances de deux sont exactement représentables. 0,5 = = 0,1b = 2^(- 1), 0,25 = 0,01b = (2^-2), 0,75 = 0,11b = (2^-1 + 2^-2) sont tous OK. Mais 1/10 = 0,000110001100011..b ne peut être exprimé que comme une somme infinie de puissances de 2, que la langue coupe à un moment donné. C'est ce découpage qui provoque ces légères erreurs.

4

De The Floating-Point Guide:

Pourquoi ne pas mes chiffres, comme 0,1 + 0,2 ajouter jusqu'à une belle ronde 0,3 et au lieu que j'obtenir un résultat bizarre comme ,30000000000000004?

Parce interne, les ordinateurs utilisent un format (en virgule flottante binaire) qui peut ne pas représenter exactement un nombre comme 0,1, 0,2 ou 0,3 du tout.

Lorsque le code est compilé ou interprété , votre « 0.1 » est déjà arrondi au nombre le plus proche dans ce format , qui se traduit par une petite erreur d'arrondi avant même le calcul arrive.

Le site contient des explications détaillées ainsi que des informations sur la façon de résoudre le problème (et de décider s'il s'agit d'un problème dans votre cas).

+0

Plus simple réponse. – hamzox

15

Ce n'est pas un problème JS mais un problème informatique plus général.Numéro flottant ne peut pas stocker correctement les nombres décimaux, car ils stockent des choses dans binaire Par exemple:

0.5 is store as b0.1 
but 0.1 = 1/10 so it's 1/16 + (1/10-1/16) = 1/16 + 0.0375 
0.0375 = 1/32 + (0.0375-1/32) = 1/32 + 00625 ... etc 

so in binary 0.1 is 0.00011... 

mais c'est sans fin. Sauf que l'ordinateur doit s'arrêter à un moment donné. Donc, si dans notre exemple nous nous arrêtons à 0,00011, nous avons 0.09375 au lieu de 0.1.

De toute façon le point est, cela ne dépend pas de la langue, mais sur l'ordinateur. Ce qui dépend de la langue, c'est comment vous affichez les nombres. Habituellement, la langue arrondit les nombres à une représentation acceptable. Apparemment, JS ne le fait pas.

Donc, ce que vous avez à faire (le nombre en mémoire est assez précis) est simplement de dire à JS comment arrondir "joliment" nombre lors de la conversion en texte.

Vous pouvez essayer la fonction sprintf qui vous donne un contrôle précis de l'affichage d'un nombre.