TheRec
vendredi 21 juillet 2006 à 22:41
Mouais... c'est relativement fiable, cela dépend d'où est utilisé le script (environnement 32 ou 64 bits, ...), la comparaison de nombres à virgule flottante n'est jamais vraiment fiable... Pour justifier cette remarque je vais citer le manuel PHP (encore... je vous rassure, je lis d'autres truc des fois

) :
CITATION
Précision des nombres décimaux
Il est fréquent que de simples fractions décimales telles que 0.1 ou 0.7 ne puissent être converties au format interne binaire sans une légère perte de précision. Cela peut conduire à des résultats étonnants : par exemple, floor((0.1+0.7)*10) retournera 7 au lieu de 8 car le résultat de la représentation interne est 7.9999999999....
Tout ceci est lié au fait qu'il est impossible d'exprimer certaines fractions en un nombre fini de chiffres. Par exemple 1/3 s'écrira 0.3333333... en mode décimal.
Ne faites donc jamais confiance aux nombres à virgule jusqu'à leur dernière décimale et ne comparez jamais ces nombres avec l'opérateur d'égalité. Si vous avez besoin d'une précision particulière, reportez-vous au traitement des nombres de grande taille avec les bibliothèques BC ou GMP.
C'est pourquoi lorsqu'on veut comparer des nombres à virgule flottante on utilise une marge de précision généralement nommée "Epsilon" (lettre grecque) qui dépend de l'environnement en question...
Donc, pour vérifier une "égalité" on procèderait ainsi : |nombre1 - nombre2| < epsilon
Où
epsilon est minime, par exemple : 0.0001
On peut penser que cela n'amène rien car le calcul produit également un nombre à virgule flottante, mais cette précision est utilisée au sein du même système binaire et donc par rapport à celui-ci elle est significative !
Cela peut sembler être du "bricolage", mais c'est la seule possibilité à ma connaissance d'éviter une majorité de problèmes lors de la représentation de nombres à virgule flottante et de leurs comparaisons.
C'est un peu hors sujet, mais je tiens juste à préciser cela si tu viens à effectuer des comparaisons sur des nombres à virgule flottante.
Ci-après les 3 fonctions que j'utilise généralement,
CODE
/**
* Compare equality of two floats with a presision factor : $epsilon
*
* @date 2005-04-02
* @param float $first First variable for comparaison
* float $second Second variable for comparaison
* float $epsilon Small factor to work around the float imprecision
* @return bool true = equal, false = not equal
*/
function floatEqual($first,$second,$epsilon) {
return (abs($first - $second) < $epsilon);
}
/**
* Compare two floats to see if $first is greater or equal to $last
*
* @date 2005-04-02
* @param float $first First variable for comparaison
* float $second Second variable for comparaison
* float $epsilon Small factor to work around the float imprecision
* @return bool true = greater or equal, false = smaller
*/
function floatGreaterOrEqual($first,$second,$epsilon) {
return (floatEqual($first,$second,$epsilon) || (($first > ($second - $epsilon)) && ($first > ($second + $epsilon))));
}
/**
* Compare two floats to see if $first is lesser or equal to $last
*
* @date 2005-04-02
* @param float $first First variable for comparaison
* float $second Second variable for comparaison
* float $epsilon Small factor to work around the float imprecision
* @return bool true = lesser or equal, false = greater
*/
function floatLesserOrEqual($first,$second,$epsilon) {
return (floatEqual($first,$second,$epsilon) || (($first < ($second - $epsilon)) && ($first < ($second + $epsilon))));
}