Arbeiten mit Floats

Nette\Utils\Floats ist eine statische Klasse mit nützlichen Funktionen zum Vergleichen von Dezimalzahlen.

Installation:

composer require nette/utils

Alle Beispiele setzen voraus, dass ein Alias erstellt wurde:

use Nette\Utils\Floats;

Motivation

Sie fragen sich vielleicht, warum überhaupt eine Klasse zum Vergleichen von Floats? Ich kann doch die Operatoren <, >, === verwenden und bin fertig. Das stimmt nicht ganz. Was denken Sie, was dieser Code ausgibt?

$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 ausgegeben hat.

Bei mathematischen Operationen mit Dezimalzahlen kommt es aufgrund der Konvertierung zwischen dem Dezimal- und dem Binärsystem zu Fehlern. Zum Beispiel ergibt 0.1 + 0.2 0.300000000000000044…. Deshalb müssen wir beim Vergleich einen kleinen Unterschied ab einer bestimmten Dezimalstelle tolerieren.

Und genau das macht 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 Ausnahme \LogicException geworfen.

Die Klasse Floats toleriert Unterschiede kleiner als 1e-10. Wenn Sie mit höherer Präzision arbeiten müssen, verwenden Sie stattdessen die BCMath-Bibliothek.

Vergleich von Floats

areEqual (float $a, float $b)bool

Gibt true zurück, wenn $a = $b.

Floats::areEqual(10, 10.0); // true

isLessThan (float $a, float $b)bool

Gibt true zurück, wenn $a < $b gilt.

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 gilt.

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 gilt.

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 gilt.

Floats::isGreaterThanOrEqualTo(9.5, 10.2);  // false
Floats::isGreaterThanOrEqualTo(10.2, 10.2); // true

compare (float $a, float $b)int

Wenn $a < $b, gibt -1 zurück, wenn sie gleich sind, gibt 0 zurück, und wenn $a > $b, gibt 1 zurück.

Kann beispielsweise mit der Funktion usort verwendet werden.

$arr = [1, 5, 2, -3.5];
usort($arr, [Float::class, 'compare']);
// $arr ist jetzt [-3.5, 1, 2, 5]

Hilfsfunktionen

isZero (float $value): bool

Gibt true zurück, wenn der Wert gleich 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
Version: 4.0