Page 1 sur 1

Problème avec des floats

Posté : 16 sept. 2016, 18:10
par carte-sd
Bonjour à tous,
Ma confusion avec le type float en php ne fait que s'accentuer, j'ai deux méthodes qui renvoient un résultat de type float, voici ce qu'il se produit lorsque je les compare :

Code : Tout sélectionner

$a = (float) transaction::solde(); $b = (float) $compte->solde(); var_dump($a, $b, $a === $b, bccomp($a, $b, 2)); // Comparaison à 2 décimales avec bccomp, 0 = identique
E:\users\....php:213:float 1927.53
E:\users\....php:213:float 1927.53
E:\users\....php:213:boolean false
E:\users\....php:213:int 0
Et si je change le solde, j'ajoute admettons +265:
E:\users\....php:213:float 2192.53
E:\users\....php:213:float 2192.53
E:\users\....php:213:boolean true
E:\users\....php:213:int 0
Selon son humeur, php va me renvoyer true ou false, je suis totalement largué, comment interpréter ça alors que var_dump me renvoie un nombre identique en type et en quantité ?

Re: Problème avec des floats

Posté : 16 sept. 2016, 22:51
par @rthur
Fait nous un exemple complet avec des variables qu'on puisse reproduire ton problème.

C'est bccomp() qui devrait te donner le bon résultat

Re: Problème avec des floats

Posté : 17 sept. 2016, 15:10
par carte-sd
Je me suis cassé la tête à reproduire le problème et j'y suis enfin parvenu. Visiblement c'est un problème d'arrondi qui se fait soit vers le haut, soit vers le bas...

Code : Tout sélectionner

$a = 5.99; $b = 5.02; $c = $b + 0.97; var_dump($a, $c, $a === $c); // float 5.99 / float 5.99 / false printf('$a: %.15f, $c: %.15f', $a, $c); // $a: 5.990000000000000, $c: 5.989999999999999 $a = 5.98; $b = 5.03; $c = $b + 0.95; var_dump($a, $c, $a === $c); // float 5.98 / float 5.98 / true printf('$a: %.15f, $c: %.15f', $a, $c); // $a: 5.980000000000000, $c: 5.980000000000000
Dans le cas d'une transaction bancaire, impossible donc de savoir si ça va être arrondi vers le haut ou vers le bas, je ne m'attendais pas à ça sur un décimal à 2 chiffres.
Là comme ça sans doutes à cause de mon niveau pas très élevé je dirais que c'est un énorme bug puisque tout ceci est totalement opaque...
J'ai mis 6h à comprendre et la seule solution semble être de travailler avec des nombres faux, arrondis à la décimales grâce à gccomp. J'ai vraiment du mal à me contenter de ça :/

Re: Problème avec des floats

Posté : 17 sept. 2016, 22:39
par @rthur
Il y a un GROS avertissement sur les float dans la doc :
http://php.net/manual/fr/language.types.float.php

Et bccomp() te renvoies le bon résultat :
<?php
$a = 5.99;
$b = 5.02;
$c = $b + 0.97;
var_dump($a, $c, $a === $c, bccomp($a,$c, 2)); // float 5.99 / float 5.99 / false / 0 (qui veut dire que c'est égal)
printf('$a: %.15f, $c: %.15f', $a, $c); // $a: 5.990000000000000, $c: 5.989999999999999

$a = 5.98;
$b = 5.03;
$c = $b + 0.95;
var_dump($a, $c, $a === $c, bccomp($a,$c, 2)); // float 5.98 / float 5.98 / true / 0 (qui veut dire que c'est égal)
printf('$a: %.15f, $c: %.15f', $a, $c); // $a: 5.980000000000000, $c: 5.980000000000000

Re: Problème avec des floats

Posté : 19 sept. 2016, 09:45
par carte-sd
Encore merci @rthur, j'ai finalement compris.
J'explique ce que j'ai compris pour ceux qui passeront un jour ici. PHP stockant une valeur approchée des nombres à virgule c'est tout à fait logique que 5.03 + 0.95 puisse produire un résultat différent de 5.98, puisque le premier est le résultat de 2 valeurs approchées alors que le second n'est qu'un seul nombre. C'est une notion assez difficile à comprendre - malgré les explications que j'avais déjà lues plusieurs fois ! - mais je pense qu'elle est rentrée; la seule solution pour comparer deux nombres à virgules c'est de les couper; même si ce sont des nombres décimaux !!!