Arbeiten mit Fließkommazahlen
Nette\Utils\Floats ist eine statische Klasse mit nützlichen Funktionen zum Vergleichen von Fließkommazahlen (Floats).
Installation:
composer require nette/utils
Alle Beispiele setzen voraus, dass der folgende Alias definiert wurde:
use Nette\Utils\Floats;
Motivation
Sie fragen sich vielleicht, warum es überhaupt eine Klasse zum Vergleichen von Fließkommazahlen gibt? Man kann doch die
Operatoren <
, >
, ===
verwenden und ist fertig. Das stimmt nicht ganz. Was denken Sie,
gibt dieser Code aus?
$a = 0.1 + 0.2;
$b = 0.3;
echo $a === $b ? 'same' : 'not same';
Wenn Sie den Code ausführen, werden einige von Ihnen sicherlich überrascht sein, dass das Programm not same
ausgibt.
Bei mathematischen Operationen mit Fließkommazahlen kommt es aufgrund der Konvertierung zwischen dem Dezimal- und Binärsystem
zu Genauigkeitsfehlern. Beispielsweise ergibt 0.1 + 0.2
das Ergebnis 0.300000000000000044…
. Deshalb
müssen wir beim Vergleichen eine kleine Toleranz für Unterschiede ab einer bestimmten Dezimalstelle zulassen.
Und genau das erledigt die Klasse Floats
. Der folgende Vergleich funktioniert nun wie erwartet:
echo Floats::areEqual($a, $b) ? 'same' : 'not same'; // same
Beim Versuch, NAN
zu vergleichen, wird eine \LogicException
ausgelöst.
Die Klasse Floats
toleriert Unterschiede, die kleiner als 1e-10
sind. Wenn Sie mit
höherer Präzision arbeiten müssen, verwenden Sie stattdessen die BCMath-Bibliothek.
Vergleich von Fließkommazahlen
areEqual (float $a, float $b): bool
Gibt true
zurück, wenn $a
= $b
ist.
Floats::areEqual(10, 10.0); // true
isLessThan (float $a, float $b): bool
Gibt true
zurück, wenn $a < $b
ist.
Floats::isLessThan(9.5, 10.2); // true
Floats::isLessThan(INF, 10.2); // false
isLessThanOrEqualTo (float $a, float $b): bool
Gibt true
zurück, wenn $a <= $b
ist.
Floats::isLessThanOrEqualTo(9.5, 10.2); // true
Floats::isLessThanOrEqualTo(10.25, 10.25); // true
isGreaterThan (float $a, float $b): bool
Gibt true
zurück, wenn $a > $b
ist.
Floats::isGreaterThan(9.5, -10.2); // true
Floats::isGreaterThan(9.5, 10.2); // false
isGreaterThanOrEqualTo (float $a, float $b): bool
Gibt true
zurück, wenn $a >= $b
ist.
Floats::isGreaterThanOrEqualTo(9.5, 10.2); // false
Floats::isGreaterThanOrEqualTo(10.2, 10.2); // true
compare (float $a, float $b): int
Gibt -1
zurück, wenn $a < $b
ist, 0
, wenn sie gleich sind, und 1
, wenn
$a > $b
ist.
Kann beispielsweise mit der Funktion usort()
verwendet werden.
$arr = [1, 5, 2, -3.5];
usort($arr, [Floats::class, 'compare']);
// $arr ist jetzt [-3.5, 1, 2, 5]
Hilfsfunktionen
isZero (float $value): bool
Gibt true
zurück, wenn der Wert Null ist.
Floats::isZero(0.0); // true
Floats::isZero(0); // true
isInteger (float $value): bool
Gibt true
zurück, wenn der Wert eine ganze Zahl ist.
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