Fork me on GitHub
/ Sweet home / Blog / PHP de m... non ! float de m**** ! /

PHP de m... non ! float de m**** !

Last update: 2011-07-13 12:21:19

Besoin de comparer des décimaux en PHP ? Commencez-donc par les convertir en chaines de caractères sinon bonjour les tracas:

php > var_dump(0.7 + 0.1 == 0.8);
bool(false)
php > var_dump(0.6 + 0.1 == 0.7);
bool(true)

Si quelqu'un a une explication logique...

Depuis la doc officielle: "Ainsi, ne faites jamais confiance aux derniers chiffres d'un nombre décimal, mais aussi, ne comparez jamais l'égalité de 2 nombres décimaux."

Splendide.


<< Dernières productions
Traitement de données encodées en JSON avec Java >>
 

Comments

jocelyn

0.666666669 <> 0.7 c'est bien connu !

mageekguy

À ce niveau, tous les langages sont plus ou moins à la même enseigne.
J'ai eu le même style de problèmes sur des calculs de radiosité/lancer
de rayon dans des programmes en C++, par exemple.
Cela tient à la façon dont sont représentés les flottants en mémoire.
En résumé, la précision absolue n'existe pas, tout est plus ou moins
arrondie suivant le nombre représenté.
Comme le dit si bien wikipedia, les flottants sont des approximations de
nombres réels, avec tous les désagréments qui vont avec cette
approximation.
Pour plus d'informations : http://fr.wikipedia.org/wiki/Nombre_flottant.
Il n'y a plus de cours d'architecture dans les cursus informatique
français ?

mageekguy

D'ailleurs, je n'avais pas suivi ton lien vers la doc de PHP, et je viens
de le faire, et tout cela est très bien expliqué.

Nicolas

C'est Christelle qui va être contente, youpi ;p («Tiens v'la tes
décimales !»)

desfrenes

@mageekguy: Je ne viens d'aucun cursus informatique français. Par ailleurs
cours ou pas il n'empêche que c'est archi-faux. Que tous les langages
soient merdiques est une faible consolation. D'ailleurs ce n'est pas exact,
en C je ne retrouve pas la même erreur:

mickael$ cat test.c 
#include <stdio.h>
 
int main()
{
	float test1 = 0.8;
	float test2 = 0.7 + 0.1;
	if(test1 == test2)
	{
		printf("ok\n");
	}
	test1 = 0.7;
	test2 = 0.6 + 0.1;
	if(test1 == test2)
	{
		printf("ok\n");
	}
}
mickael$ ./a.out 
ok
ok

desfrenes

Et on me souffle dans l'oreille droite que ça marche aussi en java:

public class Main
{

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args)
    {
        float test1 = 0.8f;
        float test2 = 0.7f + 0.1f;
        if (test1 == test2)
        {
            System.out.println("ok");
        }
        test1 = 0.7f;
        test2 = 0.6f + 0.1f;
        {
            System.out.println("ok");
        }
    }
}

mageekguy

Rigolons un peu...
Médites sur le résultat de ce programme C :
#include <stdio.h>

int main()
{
	float test1 = 0.8;

	if (test1 == (1.6 / 2.0))
	{
		printf("ok\n");
	}

	test1 = 0.7;

	if (test1 == (1.4 / 2.0))
	{
		printf("ok\n");
	}
}

desfrenes

Ah oui vraiment... qu'est-ce qu'on se marre...

#include <stdio.h>

int main()
{
float test1 = 0.8;
float op1 = 1.6;
float op2 = 2.0;
float op3 = 1.4;
float op4 = 2.0;


if (test1 == (op1 / op2))
{
printf("ok\n");
}

test1 = 0.7;

if (test1 == (op3 / op4))
{
printf("ok\n");
}
}

Tout ça c'est bien sympathique et ça fait sans doute bien mousser les
vrais geeks/nerds/whatever, mais ça n'apporte pas de solution propre pour
comparer deux décimaux en PHP.

mageekguy

RTFM, comme dise les geeks/nerds/whatever.
T'as la réponse dans ton billet, sous la forme d'un lien qui revoit sur la
doc de PHP qui te dit : Si vous avez besoin d'une haute précision, les
fonctions mathématiques de précision et les fonctions gmp sont
disponibles.

desfrenes

J'avais bien lu, merci, mais ça ne change rien à ma critique. Là où on
peut utiliser une bibliothèque tierce (pas toujours disponible), je
préfèrerai largement que le langage le prenne en charge. C'est un peu
comparable avec ce qu'on voit du coté des chaînes de caractères. Oui, on
peut utiliser les fonction mb_*, mais ce serait tout de même mieux si un
strlen fonctionnait "comme on peut s'y attendre" sans cette bibliothèque.
Bref, un peu de considération pour "Principle of least astonishment".

desfrenes

Allez... pour la peine je change le titre du billet.

Comment this