PHP float erreur de calcul lors de la soustraction
J'ai un drôle de problème. Si je soustrais 2 float var où l'on est le résultat d'une opération mathématique-je obtenir une valeur incorrecte.
Exemple:
var_dump($remaining);
var_dump($this->hours_sub['personal']);
echo $remaining-$this->hours_sub['personal'];
Ce il le de sortie:
float 5.4
float 1.4
5.3290705182008E-15
5.4-1.4 devrait être 4
Si j'ajoute deux valeurs, le résultat est correct.
Où est mon erreur?
Il ne peut pas être un arrondi question.
C'est fonctionne bien, peut-être que vous devriez essayer
Pourquoi "Il ne peut pas être un arrondi problème."?
Parce qu'un arrondi question ne serait pas produire une valeur proche de 0 pour la différence de deux approximations 5.4 et 1,4 respectivement. Un "arrondi question" serait de produire des
Directement
Pour le moment, je ne suis pas convaincu que la question devrait être fermée à tous. Je suppose qu'il en sera TL, mais je ne suis pas sûr. Ce dont je suis sûr, c'est qu'il n'est pas dupe de ce qu'il était fermé. Pas dans les zones les plus éloignées.
bcsub()
Pourquoi "Il ne peut pas être un arrondi problème."?
Parce qu'un arrondi question ne serait pas produire une valeur proche de 0 pour la différence de deux approximations 5.4 et 1,4 respectivement. Un "arrondi question" serait de produire des
3.999...9xyz
ou 4.000...0xyz
.Directement
$a=5.4;$b=1.4;echo $a-$b;
produire le même résultat erroné?Pour le moment, je ne suis pas convaincu que la question devrait être fermée à tous. Je suppose qu'il en sera TL, mais je ne suis pas sûr. Ce dont je suis sûr, c'est qu'il n'est pas dupe de ce qu'il était fermé. Pas dans les zones les plus éloignées.
OriginalL'auteur RubbelDeCatc | 2013-06-20
Vous devez vous connecter pour publier un commentaire.
Si encore quelqu'un atteindre cette page avec des problèmes similaires où nombre flottant soustraction causes d'erreur ou d'étranges valeurs.
Je veux expliquer ce problème avec un peu plus de détails.
Il n'est pas directement lié à PHP, et il n'est pas un bug.
Cependant, chaque programmeur doit être conscient de ce problème.
Ce problème a même pris de nombreuses vies il y a deux décennies.
Le 25 février 1991 à ce problème, en nombre flottant de calcul dans un MIM-104 Patriot batterie de missile l'a empêché l'interception de l'arrivée d'un Scud missiles à Dhahran, en Arabie Saoudite, en contribuant à la mort de 28 soldats de l'Armée de terre AMÉRICAINE 14e Intendant de Détachement.
Mais pourquoi ça arrive?
La raison en est que les valeurs à virgule flottante représentent une précision limitée. Ainsi, une valeur peut
ont pas la même représentation de chaîne après le traitement. Il a également
inclut l'écriture d'une valeur à virgule flottante dans votre script, et directement
l'impression sans opérations mathématiques.
Juste un exemple simple:
Vous attendons à imprimer
0.01
, droit?Mais il apparaîtra à l'impression très étrange comme réponse
0.009999999999998
Comme les autres nombres, des nombres à virgule flottante double ou float est stocké dans la mémoire comme une chaîne de 0 et de 1. Comment virgule flottante diffère entier est dans la façon dont nous interprétons les valeurs 0 et 1 lorsque l'on veut regarder. Il existe de nombreuses normes de la façon dont ils sont stockés.
Nombres à virgule flottante sont généralement emballés dans un ordinateur, une donnée que le bit de signe, l'exposant champ, et le significande ou mantisse, de gauche à droite....
Nombres décimaux ne sont pas bien représentés en binaire en raison du manque de suffisamment d'espace. Donc, vous ne pouvez pas exprimer
1/3
exactement comme il0.3333333...
, droit? Pourquoi nous ne pouvons pas nous représenter0.01
comme un binaire nombre à virgule est pour la même raison.1/100
est0.00000010100011110101110000.....
avec une répétition de10100011110101110000
.Si
0.01
est conservé dans simplifié et système-forme tronquée de01000111101011100001010
en binaire, lorsqu'il est converti en décimal, il serait à lire comme0.0099999....
selon le système (64 bits des ordinateurs va vous donner beaucoup plus de précision de 32 bits). Système d'exploitation décide, dans ce cas, si l'imprimer comme il voit ou comment le rendre plus lisible par l'homme. Donc, il est dépendant de la machine comment ils veulent représenter. Mais il peut être protégé dans un niveau de langue avec des méthodes différentes.Si vous formatez le résultat à l'aide de
il permet d'imprimer
0.01
.C'est parce que dans ce cas vous demandez comment il doit être lu et la façon dont la précision dont vous avez besoin.
comment résoudre ce problème ?
Des décennies va aller et je dirai toujours que c'est un BUG ÉVIDENT. Nous n'avons pas de soins si elle enregistre avec
0
et1
combinaison ou que - Les inventeurs devraient avait inventé la solution pour ce faire, sans nous forcer à apprendre la programmation sur mesure pour juste pour calculer36-35.99
(c'est à dire l'enregistrer en tant que chaîne à première et de convertir retour à nombre - nous n'avons tout simplement pas de soins. Nous avons besoin de l'ordinateur pour calculer les choses simples correctement, sans aucun besoin de connaître le fonctionnement interne defloat
) .J'ai déjà passé des heures à simplement obtenir la réponse
945252744562139136 - 1
, une recherche google plusieurs fois pour un code qui peut tout obtenir cette réponse simple correctement dansphp
mais je n'ai pas encore trouvé.OriginalL'auteur Selay
En plus de l'utilisation de number_format(), il y a trois autres façons d'obtenir le résultat correct. L'une consiste à faire un peu de mathématiques, comme suit:
Voir démo
Ou, vous pouvez simplement utiliser printf():
Voir démo
Note, sans le spécificateur de précision, le printf() résultat contiendra de fuite zéro décimales, comme suit:
0.010000
Vous pouvez aussi utiliser le BC fonction Mathématique bcadd(), comme suit:
Voir démo
OriginalL'auteur slevy1
Cela a fonctionné pour moi:
Puisque le problème se produit avec virgule flottante soustraction de l'opération, j'ai décidé de l'éliminer en le transformant en un nombre entier de fonctionnement, puis de sauvegarder le résultat dans une variable point de nouveau.
Je préfère de loin cette solution parce que, fondamentalement, il n'empêche que l'erreur sur le calcul plutôt que de rouding le résultat avec d'autres fonctions.
OriginalL'auteur mjaning