Travailler avec les flottants
Nette\Utils\Floats est une classe statique avec des fonctions utiles pour comparer les nombres décimaux.
Installation :
composer require nette/utils
Tous les exemples supposent qu'un alias a été créé :
use Nette\Utils\Floats;
Motivation
Vous vous demandez pourquoi une classe pour comparer les flottants ? Après tout, je peux utiliser les opérateurs
<, >, === et c'est réglé. Ce n'est pas tout à fait vrai. Que pensez-vous que ce
code affichera ?
$a = 0.1 + 0.2;
$b = 0.3;
echo $a === $b ? 'same' : 'not same';
Si vous exécutez le code, certains d'entre vous seront sûrement surpris que le programme ait affiché
not same.
Lors des opérations mathématiques avec des nombres décimaux, des erreurs se produisent en raison de la conversion entre les
systèmes décimal et binaire. Par exemple, 0.1 + 0.2 donne 0.300000000000000044…. C'est pourquoi,
lors de la comparaison, nous devons tolérer une petite différence à partir d'une certaine décimale.
Et c'est exactement ce que fait la classe Floats. La comparaison suivante fonctionnera déjà comme prévu :
echo Floats::areEqual($a, $b) ? 'same' : 'not same'; // same
En essayant de comparer NAN, elle lève une exception \LogicException.
La classe Floats tolère des différences inférieures à 1e-10. Si vous avez besoin de
travailler avec une plus grande précision, utilisez plutôt la bibliothèque BCMath.
Comparaison de flottants
areEqual(float $a, float $b): bool
Retourne true si $a = $b.
Floats::areEqual(10, 10.0); // true
isLessThan(float $a, float $b): bool
Retourne true si $a < $b.
Floats::isLessThan(9.5, 10.2); // true
Floats::isLessThan(INF, 10.2); // false
isLessThanOrEqualTo(float $a, float $b): bool
Retourne true si $a <= $b.
Floats::isLessThanOrEqualTo(9.5, 10.2); // true
Floats::isLessThanOrEqualTo(10.25, 10.25); // true
isGreaterThan(float $a, float $b): bool
Retourne true si $a > $b.
Floats::isGreaterThan(9.5, -10.2); // true
Floats::isGreaterThan(9.5, 10.2); // false
isGreaterThanOrEqualTo(float $a, float $b): bool
Retourne true si $a >= $b.
Floats::isGreaterThanOrEqualTo(9.5, 10.2); // false
Floats::isGreaterThanOrEqualTo(10.2, 10.2); // true
compare(float $a, float $b): int
Si $a < $b, retourne -1, s'ils sont égaux, retourne 0 et si
$a > $b, retourne 1.
Peut être utilisé par exemple avec la fonction usort.
$arr = [1, 5, 2, -3.5];
usort($arr, [Floats::class, 'compare']);
// $arr est maintenant [-3.5, 1, 2, 5]
Fonctions utilitaires
isZero(float $value): bool
Retourne true si la valeur est égale à zéro.
Floats::isZero(0.0); // true
Floats::isZero(0); // true
isInteger(float $value): bool
Retourne true si la valeur est un entier.
Floats::isInteger(0); // true
Floats::isInteger(0.0); // true
Floats::isInteger(-5.0); // true
Floats::isInteger(-5.1); // false
Floats::isInteger(INF); // false
Floats::isInteger(NAN); // false