Question Comparer les flotteurs dans php


Je veux comparer deux flottants 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 renvoie le résultat du else condition au lieu de la if condition, même si $a et $b sont identiques. Existe-t-il un moyen spécial de gérer / comparer les flottants en PHP?

Si oui, alors aidez-moi à résoudre ce problème.

Ou y a-t-il un problème avec la configuration de mon serveur?


106
2018-06-30 11:51


origine


Réponses:


Si vous le faites comme ça, ils devrait être le même. Mais notez qu'une caractéristique des valeurs à virgule flottante est que les calculs qui sembler pour aboutir à la même valeur, il n'est pas nécessaire d'être identique. Donc si $a est un littéral .17 et $b arrive là par un calcul, il se peut bien qu'ils soient différents, mais tous deux affichent la même valeur.

Habituellement, vous ne comparez jamais des valeurs à virgule flottante comme égalité, vous devez utiliser la plus petite différence acceptable:

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

Quelque chose comme ca.


187
2018-06-30 11:57



Lisez d'abord l'avertissement rouge http://www.php.net/manual/en/language.types.float.php. Vous ne devez jamais comparer les flotteurs pour l'égalité. Vous devez utiliser la technique epsilon.

Par exemple:

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

EPSILON est constant représentant un très petit nombre (vous devez le définir)


44
2018-06-30 11:59



Ou essayez d'utiliser les fonctions mathématiques bc:

<?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)

22
2017-12-27 10:15



Comme indiqué précédemment, soyez très prudent lorsque vous effectuez des comparaisons en virgule flottante (égales, supérieures ou inférieures à) en PHP. Cependant, si vous n'êtes intéressé que par 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'arrondi à 2 décimales (ou 3 ou 4) provoquera le résultat attendu.


8
2017-07-10 18:07



Il serait préférable d'utiliser comparaison PHP native:

bccomp($a, $b, 3)
// Third parameter - the optional scale parameter
// is used to set the number of digits after the decimal place
// which will be used in the comparison. 

Retourne 0 si les deux opérandes sont égaux, 1 si le left_operand est   plus grand que le right_operand, -1 sinon.


8
2018-06-21 11:01



Si vous avez des valeurs à virgule flottante à comparer à l'égalité, un moyen simple d'éviter le risque de arrondissement interne stratégie du système d’exploitation, de la langue, du processeur, etc., consiste à comparer représentation de chaîne des valeurs, comme:

if (''. $ a === ''. $ b) {...}

De cette façon, vous pouvez voir l'égalité, et la réponse de PHP sera égale à vos souhaits. Si c'est égal pour toi quand tu lire les valeurs, alors la déclaration sera vraie, comme prévu


3
2017-11-07 10:48



Voici la solution pour comparer des nombres flottants ou décimaux

//$fd['someVal'] = 2.9;
//$i for loop variable steps 0.1
if((string)$fd['someVal']== (string)$i)
{
    //Same
}

Lancer un decimal variable à string et vous irez bien.


2
2018-05-11 11:47



Si vous avez un nombre limité de décimales qui sera acceptable, les éléments suivants fonctionnent (bien qu'avec des performances plus lentes que la solution epsilon):

$a = 0.17;
$b = 1 - 0.83; //0.17

if (number_format($a, 3) == number_format($b, 3)) {
    echo 'a and b are same';
} else {
    echo 'a and b are not same';
}

2
2018-04-09 01:41



Si vous l'écrivez comme cela, cela fonctionnera probablement, alors j'imagine que vous l'avez simplifié pour la question. (Et garder la question simple et concise est normalement une très bonne chose.)

Mais dans ce cas, j'imagine qu'un résultat est un calcul et un résultat est une constante.

Cela viole une règle cardinale de programmation en virgule flottante: Ne faites jamais de comparaisons d'égalité.

Les raisons en sont un peu subtiles1 mais ce qui est important à retenir, c'est qu'ils ne fonctionnent généralement pas (sauf ironiquement pour les valeurs intégrales) et que l'alternative est une comparaison floue du type:

if abs(a - y) < epsilon



1. L'un des problèmes majeurs concerne la manière dont nous écrivons les nombres dans les programmes. Nous les écrivons sous forme de chaînes décimales et, par conséquent, la plupart des fractions écrites n’ont pas de représentation exacte de la machine. Ils n'ont pas de formes finies exactes car ils se répètent en binaire. Chaque fraction de machine est un nombre rationnel de la forme x / 2n. Maintenant, les constantes sont décimales et chaque constante décimale est un nombre rationnel de la forme x / (2n * 5m). Le 5m les nombres sont impairs, donc il n'y a pas 2n facteur pour l'un d'eux. Ce n'est que lorsque m == 0 est-il une représentation finie à la fois dans l'expansion binaire et décimale de la fraction. Donc, 1.25 est exact parce que c'est 5 / (22* 50) mais 0.1 n'est pas parce que c'est 1 / (20* 51). En fait, dans la série 1.01 .. 1,99, seuls 3 des nombres sont exactement représentables: 1,25, 1,50 et 1,75.


1
2018-03-26 06:27