167 votes

Comparer les flotteurs en php

Je veux comparer deux flotteurs en PHP, comme dans cet exemple de code:

$a = 0.17;
$b = 1 - 0.83; //0.17
if($a == $b ){
 echo 'a and b are same';
}
else {
 echo 'a and b are not same';
}

Dans ce code, il retourne le résultat de l' else état au lieu de l' if condition, même si $a et $b sont même. Est-il une manière particulière de traiter les comparer flotteurs en PHP?

Si oui, alors s'il vous plaît m'aider à résoudre ce problème.

Ou est-il un problème avec mon serveur config?

242voto

Joey Points 148544

Si vous faites comme cela, ils doivent être la même. Mais notez qu'une caractéristique de valeurs à virgule flottante est que les calculs qui semblent résulter de la même valeur n'avez pas besoin d'être réellement identiques. Donc, si $a est un littéral .17 et $b y arrive par le biais d'un calcul, il peut très bien qu'ils sont différents, mais les deux affichent la même valeur.

Habituellement, vous ne comparez jamais les valeurs à virgule flottante pour l'égalité comme cela, vous devez utiliser une plus petite différence acceptable:

if (abs(($a-$b)/$b) < 0.00001) {
  echo "same";
}

Quelque chose comme ça.

72voto

Andrey Points 36869

Lire l'avertissement rouge premier http://www.php.net/manual/en/language.types.float.php. Il ne faut jamais comparer les flotteurs pour l'égalité. Vous devez utiliser l'epsilon technique.

Par exemple:

if (abs($a-$b) < EPSILON) { … }

EPSILON est constante représentant un très petit nombre (il faut le définir)

32voto

Mario Points 121

Ou essayez d'utiliser bc fonctions mathématiques:

<?php
$a = 0.17;
$b = 1 - 0.83; //0.17

echo "$a == $b (core comp oper): ", var_dump($a==$b);
echo "$a == $b (with bc func)  : ", var_dump( bccomp($a, $b)==0 );

Résultat:

0.17 == 0.17 (core comp oper): bool(false)
0.17 == 0.17 (with bc func)  : bool(true)

20voto

Michael Butler Points 1872

Comme dit précédemment, être très prudent lorsque vous faites virgule flottante comparaisons (égal à, supérieur ou inférieur) en PHP. Toutefois, si vous n'êtes jamais intéressé à quelques chiffres significatifs, vous pouvez faire quelque chose comme:

$a = round(0.17, 2);
$b = round(1 - 0.83, 2); //0.17
if($a == $b ){
    echo 'a and b are same';
}
else {
    echo 'a and b are not same';
}

L'utilisation de l'arrondi à 2 décimales (ou 3, ou 4) fera en sorte que le résultat attendu.

0voto

Adam Wright Points 31715

Je déteste dire ça, mais "fonctionne pour moi:

Beech:~ adamw$ php -v
PHP 5.3.1 (cli) (built: Feb 11 2010 02:32:22) 
Copyright (c) 1997-2009 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2009 Zend Technologies
Beech:~ adamw$ php -f test.php
a and b are same

Maintenant, à virgule flottante les comparaisons sont en général difficile des choses que vous pourriez vous attendre à être les mêmes ne le sont pas (à cause des erreurs d'arrondi et/ou de représentation des nuances). Vous voudrez peut-être lire http://floating-point-gui.de/

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X