Εργασία με δεκαδικούς αριθμούς (floats)
Η Nette\Utils\Floats είναι μια στατική κλάση με χρήσιμες συναρτήσεις για τη σύγκριση δεκαδικών αριθμών.
Εγκατάσταση:
composer require nette/utils
Όλα τα παρακάτω παραδείγματα προϋποθέτουν τη δημιουργία ενός ψευδωνύμου:
use Nette\Utils\Floats;
Κίνητρο
Αναρωτιέστε, γιατί μια κλάση για τη σύγκριση δεκαδικών αριθμών; Αφού
μπορώ να χρησιμοποιήσω τους τελεστές <, >, === και
είμαι καλυμμένος. Δεν είναι απολύτως αλήθεια. Τι νομίζετε ότι θα
εκτυπώσει ο παρακάτω κώδικας;
$a = 0.1 + 0.2;
$b = 0.3;
echo $a === $b ? 'same' : 'not same';
Αν εκτελέσετε τον κώδικα, κάποιοι από εσάς σίγουρα θα εκπλαγείτε που
το πρόγραμμα εκτύπωσε not same.
Κατά τις μαθηματικές πράξεις με δεκαδικούς αριθμούς, προκύπτουν
σφάλματα λόγω της μετατροπής μεταξύ του δεκαδικού και του δυαδικού
συστήματος. Για παράδειγμα, το 0.1 + 0.2 δίνει 0.300000000000000044….
Γι' αυτό, κατά τη σύγκριση, πρέπει να ανεχόμαστε μια μικρή διαφορά από
ένα συγκεκριμένο δεκαδικό ψηφίο.
Και αυτό ακριβώς κάνει η κλάση Floats. Η παρακάτω σύγκριση θα
λειτουργήσει όπως αναμένεται:
echo Floats::areEqual($a, $b) ? 'same' : 'not same'; // same
Μια προσπάθεια σύγκρισης του NAN προκαλεί μια εξαίρεση
\LogicException.
Η κλάση Floats ανέχεται διαφορές μικρότερες από 1e-10.
Αν χρειάζεστε να εργαστείτε με μεγαλύτερη ακρίβεια, χρησιμοποιήστε
καλύτερα τη βιβλιοθήκη BCMath.
Σύγκριση δεκαδικών αριθμών
areEqual(float $a, float $b): bool
Επιστρέφει true αν $a = $b.
Floats::areEqual(10, 10.0); // true
isLessThan(float $a, float $b): bool
Επιστρέφει true αν ισχύει $a < $b.
Floats::isLessThan(9.5, 10.2); // true
Floats::isLessThan(INF, 10.2); // false
isLessThanOrEqualTo(float $a, float $b): bool
Επιστρέφει true αν ισχύει $a <= $b.
Floats::isLessThanOrEqualTo(9.5, 10.2); // true
Floats::isLessThanOrEqualTo(10.25, 10.25); // true
isGreaterThan(float $a, float $b): bool
Επιστρέφει true αν ισχύει $a > $b.
Floats::isGreaterThan(9.5, -10.2); // true
Floats::isGreaterThan(9.5, 10.2); // false
isGreaterThanOrEqualTo(float $a, float $b): bool
Επιστρέφει true αν ισχύει $a >= $b.
Floats::isGreaterThanOrEqualTo(9.5, 10.2); // false
Floats::isGreaterThanOrEqualTo(10.2, 10.2); // true
compare(float $a, float $b): int
Αν $a < $b, επιστρέφει -1, αν είναι ίσα επιστρέφει
0, και αν $a > $b επιστρέφει 1.
Μπορεί να χρησιμοποιηθεί, για παράδειγμα, με τη συνάρτηση
usort.
$arr = [1, 5, 2, -3.5];
usort($arr, [Floats::class, 'compare']);
// $arr είναι τώρα [-3.5, 1, 2, 5]
Βοηθητικές συναρτήσεις
isZero(float $value): bool
Επιστρέφει true αν η τιμή είναι ίση με μηδέν.
Floats::isZero(0.0); // true
Floats::isZero(0); // true
isInteger(float $value): bool
Επιστρέφει true αν η τιμή είναι ακέραιος αριθμός.
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