Εργασία με δεκαδικούς αριθμούς (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
έκδοση: 4.0