2010-08-18 5 views
3
$a = ((0.1 + 0.7) * 10) == (int)((0.1 + 0.7) * 10); 

PHP renvoie la valeur false.Arrondi dans PHP

Quelqu'un pourrait-il m'expliquer pourquoi cela se produit? rendements 8 premiers, deuxièmes 7.

+2

Si jamais vous voulez plonger dans la réponse longue: http://docs.sun.com/source/806-3568/ncg_goldberg.html – webbiedave

+0

Jetez également un oeil à mon article http://www.exploringbinary.com/when-floats-dont-behave-like-floats/ (voir programme 2 en particulier). (Il s'agit essentiellement de plus de détails sur le phénomène décrit dans les réponses ci-dessous, bien que dans un contexte différent). –

Répondre

5

arithmétique à virgule flottante est pas précis. Au lieu de 8.0 exactement, vous pouvez obtenir 7.999 ... qui est tronqué à 7 lorsqu'il est converti en nombre entier.

echo number_format((0.1 + 0.7) * 10, 20); 

Résultat:

7.99999999999999911182 
+2

Cela ne aide pas que 'var_dump ((0.1 + 0.7) * 10);' arrondit à 'float (8)' pour la sortie. –

0

Comme opérant sur les nombres à virgule flottante ne sont pas précis à 100%, propably avant la valeur de coulée de l'expression est quelque chose comme 7,9999 ...

14

Citant le big fat red warning in the PHP Manual on Floating Point Precision:

Il est typique que des fractions décimales simples comme 0.1 ou 0.7 ne peut pas être converti en leurs homologues binaires internes sans une petite perte de précision. Cela peut conduire à des résultats confus: par exemple, floor((0.1+0.7)*10) retournera généralement 7 au lieu du 8 attendu, puisque la représentation interne sera quelque chose comme 7.9.

Ceci est dû au fait qu'il est impossible d'exprimer certaines fractions en notation décimale avec un nombre fini de chiffres. Par exemple, 1/3 sous forme décimale devient 0.3.

Alors, ne faites jamais confiance aux résultats des nombres flottants au dernier chiffre, et ne comparez jamais les nombres à virgule flottante pour l'égalité. Si une plus grande précision est nécessaire, les fonctions the arbitrary precision math functions et gmp sont disponibles.

+0

En particulier, seuls les nombres fractionnaires qui peuvent être représentés sous la forme 'p/q', où' q' est un entier de 2 et 'p' est un nombre entier, peuvent être exprimés exactement, avec un nombre fini de bits. – Artefacto

1

De The Flaoting-Point Guide (cliquez pour des explications détaillées):

Car en interne, les ordinateurs utilisent un format (virgule flottante binaire) qui ne peut pas représenter avec précision un certain nombre comme 0,1, 0,2 ou 0,3 tout au.

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.

0

Vous pouvez faire la comparaison de cette façon:

$a = round(((0.1 + 0.7) * 10), 1) == (int)round(((0.1 + 0.7) * 10), 1);