Éviter les problèmes avec le JavaScript est bizarre décimal calculs
Je il suffit de lire sur MDN que l'une des bizarreries de JS de la gestion des numéros en raison de tout ce qui se "double précision 64 bits format IEEE 754 valeurs" est que lorsque vous faites quelque chose comme .2 + .1
vous obtenez 0.30000000000000004
(c'est ce que l'article se lit, mais j'ai 0.29999999999999993
dans Firefox). Donc:
(.2 + .1) * 10 == 3
évalue à false
.
Cela semble comme il serait très problématique. Donc, ce qui peut être fait pour éviter des bugs en raison de la imprécis décimal calculs en JS?
J'ai remarqué que si vous ne 1.2 + 1.1
vous obtenez la bonne réponse. Alors, faut-il juste d'éviter toute forme de maths qui implique des valeurs inférieures à 1? Parce que cela semble très peu pratique. Existe-il d'autres dangers à faire des maths en JS?
Edit:
Je comprends que beaucoup de fractions décimales ne peuvent pas être stockées sous forme binaire, mais la façon dont la plupart des autres langues que j'ai rencontrés semblent traiter l'erreur (comme JS gère les nombres plus grand que 1) semble plus intuitif, donc je ne suis pas habitué à cela, et c'est pourquoi je veux voir comment d'autres programmeurs pour faire face à ces calculs.
- Les nombres à virgule flottante près de jamais parfaitement comparer à d'autres numéros, dans n'importe quelle langue.
- L'arrondissement est votre ami.
- Donc, vous devez multiplier le tout par une puissance de 10, puis arrondir à l'entier le plus proche?
- PHP, MySQL, Perl, VB, et la plupart des langues que j'ai utilisé dans le passé n'ont jamais eu aucun problème avec ces types de calculs.
$ php -r 'var_dump((0.1 + 0.2) * 10 == 3);'
→bool(false)
🙂- Je corrige la position des mains. Je n'ai jamais remarqué ça avant.
Vous devez vous connecter pour publier un commentaire.
Dans de telles situations, vous serait typiquement à plutôt utiliser un epsilon estimation.
Quelque chose comme (pseudo-code)
où epsilon est quelque chose comme 0.00000001, ou quelle que soit la précision dont vous avez besoin.
Avoir une lecture rapide à La comparaison des nombres à virgule flottante
)
là, sinon tout à fait d'accord.1.2 + 1.1 peut être ok, mais 0.2 + 0.1 peuvent ne pas être ok.
C'est un problème dans pratiquement toutes les langues qui est en usage aujourd'hui. Le problème est que le 1/10 ne peut pas être correctement représentée comme une fraction binaire comme 1/3 ne peut pas être représenté comme une fraction décimale.
Les solutions de contournement consiste en l'arrondissant à seulement le nombre de décimales que vous avez besoin et de travailler avec des chaînes, qui sont exactes:
ou vous pouvez convertir des nombres d'après:
ou de l'utilisation des Mathématiques.tour:
où
X
est une partie de la puissance de 10 par exemple 100 ou 10000 - en fonction de la précision que vous avez besoin.Ou vous pouvez utiliser cents au lieu de dollars lors du comptage de l'argent:
De cette façon que vous ne travaillez qu'avec des entiers et que vous n'avez pas à vous soucier de décimal et binaire fractions à tous.
2017 mise à Jour
La situation de représenter les nombres en JavaScript peut-être un peu plus compliqué que d'habitude. Il l'habitude d'être le cas que nous avons eu seulement un type numérique en JavaScript:
Ce n'est plus le cas - non seulement il y a actuellement plus de types numériques en JavaScript aujourd'hui, d'autres sont sur le chemin, y compris une proposition visant à ajouter une précision arbitraire entiers à ECMAScript, et, espérons-le, en précision arbitraire décimales suivra - voir cette réponse pour plus de détails:
Voir aussi
Une autre réponse pertinente avec quelques exemples de la façon de traiter les calculs:
real
répondretoFixed
renvoie une chaîne représentant un nombre, vous ne savez pas si c'est ce que vous voulez.Cela permettra de réduire la précision des nombres réels, mais résout le problème si vous ne travaillez pas avec des valeurs très faibles.
Par exemple:
après l'opération proposée, vous obtiendrez de 0,3, Mais n'importe quelle valeur entre:
sera également considéré comme 0.3
Compréhension des erreurs d'arrondi dans l'arithmétique à virgule flottante n'est pas pour les timides! Fondamentalement, les calculs sont effectués comme si il y avait de l'infini bits de précision disponible. Le résultat est arrondi selon des règles fixées dans les spécifications IEEE.
Des arrondis peut jeter quelques funky réponses:
Ce un tout un ordre de grandeur out. C'est une erreur d'arrondi!
Pour toute architecture à virgule flottante, il y a un certain nombre qui représente le plus petit intervalle entre les distinguer des nombres. Elle est appelée EPSILON.
Il sera une partie de l'EcmaScript standard dans un avenir proche. En attendant, vous pouvez la calculer comme suit:
Vous pouvez alors l'utiliser, à quelque chose comme ceci:
Ou, depuis des erreurs d'arrondi peuvent s'accumuler de façon alarmante, vous souhaiterez peut-être utiliser
delta /2
oudelta * delta
plutôt quedelta
.Vous avez besoin d'un peu d'erreur de commande.
Faire un peu de double comparaison de la méthode:
Il y a les bibliothèques qui cherchent à résoudre ce problème mais si vous ne voulez pas inclure l'un de ceux (ou ne peuvent pas pour une raison quelconque, comme de travailler à l'intérieur d'un GTM variable), alors vous pouvez utiliser cette petite fonction que j'ai écrit:
Utilisation:
Voici la fonction: