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
version: 4.0