2010-11-21 5 views
5

echo (int) ((0.1+0.7) * 10);Problèmes d'arrondi d'entiers PHP

Pourquoi la sortie ci-dessus 7? Je comprends comment PHP arrondit vers 0, mais n'est pas (0.1+0.7) * 10 évalué comme un flottant, puis casté comme un entier?

Merci!

+0

Je pense que cela se produit dans n'importe quelle langue, et c'est parce que la façon dont les nombres à virgule flottante sont gérés en interne – Quamis

Répondre

7

Il y a une perte de précision lorsque les décimales sont converties en interne en leur équivalent binaire. La valeur calculée sera quelque chose comme 7,9+ au lieu de la valeur attendue 8.

Si vous avez besoin d'une grande précision, utilisez la famille de fonctions GMP ou la bibliothèque bcmath.

+0

+1 Une bibliothèque comme 'bcmath' est le chemin à parcourir. –

0

Je n'ai pas php installé, mais en python:

$ python 
>>> 0.1+0.7 
0.79999999999999993 
>>> 

Tous les nombres en base 10 peuvent être représentés avec précision dans le système de base 2. Consultez l'article Wikipedia:

section Fractions en binaire. En particulier, cette ligne:

Fraction Decimal  Binary Fractional Approx. 
1/10 0.1  0.000110011... 1/16+1/32+1/256... 

1/10 ne peut pas être représenté d'une manière limitée dans la base 2. Ainsi, 0,1 + 0,7 ne peut être calculé avec précision dans la base 2.

Jamais supposer flottante les calculs ponctuels sont précis, il vous mordra tôt ou tard.

2

Voir le manuel:

http://php.net/manual/en/language.types.float.php

Il est typique que décimales simples fractions comme 0,1 ou 0,7 ne peuvent pas être convertis en leurs binaires internes homologues sans une petite perte de précision. Cela peut conduire à des résultats confus : par exemple, étage ((0,1 + 0,7) * 10) sera généralement retour 7 au lieu de l'attendu 8, puisque la représentation interne sera être quelque chose comme 7,9.

0

1/10 ne peut pas être représenté dans un nombre fini de chiffres binaires, tout comme 1/3 ne peut pas être représenté comme un nombre fini de 10 chiffres de base. Par conséquent, vous êtes en train d'ajouter ensemble 0,09999999999999 ... et 0,69999999999999 ... - la somme est presque 8, mais pas tout à fait.

1

Les autres réponses expliquées POURQUOI cela se produit. Cela devrait vous obtenir ce que vous voulez:

echo (int) round((0.1+0.7) * 10); 

Juste rond le flotteur avant la coulée à un int.

+0

aussi, son recommented vous n'utilisez pas réellement des flotteurs pour les calculs de devises, en raison de cette perte de précision – Quamis