Práce s floaty
Nette\Utils\Floats je statická třída s užitečnými funkcemi pro porovnávání desetinných čísel.
Instalace:
composer require nette/utils
Všechny příklady předpokládají vytvořený alias:
use Nette\Utils\Floats;
Motivace
Říkáte si, proč vlastně třída na porovnávání floatů? Vždyť můžu použít operátory <
,
>
, ===
a mám vystaráno. Není to tak úplně pravda. Co myslíte, že vypíše tento kód?
$a = 0.1 + 0.2;
$b = 0.3;
echo $a === $b ? 'same' : 'not same';
Pokud kód spustíte, někteří z vás budou určitě překvapení, že program vypsal not same
.
Při matematických operacích s desetinnými čísly dochází k chybám vlivem převodu mezi desítkovou a binární
soustavou. Třeba 0.1 + 0.2
vychází 0.300000000000000044…
. Proto při porovnávání musíme
tolerovat drobný rozdíl od určitého desetinného místa.
A to právě dělá třída Floats
. Následující porovnání už bude fungovat podle očekávání:
echo Floats::areEqual($a, $b) ? 'same' : 'not same'; // same
Při pokusu porovnávat NAN
vyhodí výjimku \LogicException
.
Třída Floats
toleruje rozdíly menší než 1e-10
. Pokud potřebujete pracovat
s větší přesností, použijte raději knihovnu BCMath.
Porovnávání floatů
areEqual(float $a, float $b): bool
Vrátí true
pokud $a
= $b
.
Floats::areEqual(10, 10.0); // true
isLessThan(float $a, float $b): bool
Vrátí true
pokud platí $a
< $b
.
Floats::isLessThan(9.5, 10.2); // true
Floats::isLessThan(INF, 10.2); // false
isLessThanOrEqualTo(float $a, float $b): bool
Vrátí true
pokud platí $a
<= $b
.
Floats::isLessThanOrEqualTo(9.5, 10.2); // true
Floats::isLessThanOrEqualTo(10.25, 10.25); // true
isGreaterThan(float $a, float $b): bool
Vrátí true
pokud platí $a
> $b
.
Floats::isGreaterThan(9.5, -10.2); // true
Floats::isGreaterThan(9.5, 10.2); // false
isGreaterThanOrEqualTo(float $a, float $b): bool
Vrátí true
pokud platí $a
>= $b
.
Floats::isGreaterThanOrEqualTo(9.5, 10.2); // false
Floats::isGreaterThanOrEqualTo(10.2, 10.2); // true
compare(float $a, float $b): int
Pokud jsou $a
< $b
, vrací -1
, pokud se rovnají vrací 0
a pokud je
$a
> $b
vrací 1
.
Lze použít například s funkcí usort
.
$arr = [1, 5, 2, -3.5];
usort($arr, [Float::class, 'compare']);
// $arr je nyní [-3.5, 1, 2, 5]
Pomocné funkce
isZero(float $value): bool
Vrátí true
, pokud je hodnota rovna nule.
Floats::isZero(0.0); // true
Floats::isZero(0); // true
isInteger(float $value): bool
Vrátí true
, pokud je hodnota celé číslo.
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