Matematika v PHP
- Reprezentace čísel v paměti
- Matematické operace
- Přehled základních operátorů
- Přehled základních matematických funkcí
- Zaokrouhlování
- Goniometrické funkce
- Cyklometrické funkce
- Hyperbolické funkce
- Hyperbolometrické funkce
- Příklady použití goniometrických funkcí
- Kalkulačka - zpracování matematického výrazu
- Operace s velkými čísly a přesnost výpočtů
Stejně jako v ostatních jazycích, tak i v PHP jsou čísla reprezentována ve dvojkové soustavě (soustava jedniček a nul), při některých matematických operacích proto může vycházet lehce odlišný výsledek, než bychom čekali. Tato stránka obsahuje přehled chování výpočtů v různých kontextech. Pro pochopení je potřeba aspoň základní znalost číslicové techniky a číselných soustav.
Reprezentace čísel v paměti
Způsob reprezentace čísel charakterizuje datový typ, například integer je převeden přímo ze zdrojového kódu z desítkové soustavy na dvojkovou (binární). O převod čísel se nemusíme vůbec starat, vše probíhá automaticky.
Důsledek tohoto převodu je, že maximální hodnota integeru (celé číslo) je určena podle počtu dostupných bitů v paměti. Na 32-bitovém PHP je rozsah od -2,147,483,648
do 2,147,483,647
(~ ± 2 miliardy), 64-bitové PHP má rozsah od -9,223,372,036,854,775,808
do 9,223,372,036,854,775,807
(~ ± 9 quintillionů). Maximální hodnotu můžeme vždy získat zavoláním konstanty PHP_INT_MAX
.
Desetinná čísla se ukládají do datového typu float, který má omezenou přesnost, proto se interně ukládá jako dvojice čísel, které podléhají matematické operaci mantisa * (2 ^ exponent)
. Praktický důsledek je ten, že jsme schopni na malé množství bitů uložit i relativně velké číslo (v řádu miliard), akorát ne příliš přesně.
Důsledek použití datového typu float je, že výsledkem výpočtu 1 - 0.9
není přesně 0.1
.
Příklad z webového fóra:
$x = 0.3;
$y = 0.4;
echo 0.7 - $x - $y; // vypíše -5.5511151231258E-17
Pokud ovšem čísla lehce upravíme:
$x = 6.5;
$y = 7.5;
echo 14.0 - $x - $y; // vypíše 0
Obecně o této problematice pojednává samostatný článek na webu VTM.e15.cz: Proč počítačům dělají problémy desetinná čísla, případně obecně o plovoucí řádové čárce na Wikipedii.
Obecně je dobré po výpočtu výsledek zaokrouhlit, nebo se desetinným číslům úplně vyhnout. Například cenu nebudeme ukládat v korunách (jako 14.90), ale v haléřích (jako 1490) a poté s ní pracovat přesně. O zaokrouhlování pojednává další kapitola článku.
Matematické operace
$a = 5;
$b = 3;
echo $a + $b;
Pro operace lze použít běžné matematické zvyklosti, při kterých se respektuje přednost operátorů podle pravidel matematiky (násobení má přednost před sčítáním a podobně). Hodnoty lze zapsat přímo, nebo je načítat přes proměnné.
Možná to není na první pohled zřejmé, ale u matematického příkladu se nezapisuje znak rovnítka (
=
). Z toho tedy vyplývá, že lze řešit jen jednoduchébinární operace
, které vždy pracují jen sdvěma prvky
(s rovnicemi nepočítejte, na to se musí použít specializovaná knihovna).
Přehled základních operátorů
Ve sloupci
výsledek
uvádím, co se vypíše za předpokladu, že:
$a = 5;
$b = 3;
$c = 10;
Operace | Značka | Značka slovně | Příklad zápisu | Výsledek |
---|---|---|---|---|
Sčítání | + | Plus | echo $a + $b; | 8 |
Odčítání | - | Mínus | echo $a - $b; | 2 |
Násobení | * | Hvězdička | echo $a * $b; | 15 |
dělení | / | Lomítko | echo $a / $b; | 1.66666666667 |
Závorky | ( ) | Závorky | echo $a + ($b * $c); | 35 |
Spojování řetězců | . | Tečka | echo $a . $b . $c; | 5310 |
Zbytek po dělení | % | Procento | echo $a % $b; | 2 |
Přičtení jedničky | ++ | dva plusy | echo $a++; | 6 |
Odečtení jedničky | -- | dva mínusy | echo $a--; | 4 |
Mocnina | ** | dvě hvězdičky | echo $a ** $b; | 125 |
Operátor mocniny (dvojitá hvězdička) je dostupný až od PHP 7.1. V jiných verzí PHP je nutné použít univerzální funkci
pow($a, $b)
.
Přehled základních matematických funkcí
Pokud řešíte nějaký běžný výpočetní úkol, tak s největší pravděpodobností již existuje funkce přímo v PHP, zde je jejich komentovaný přehled.
Zaokrouhlování
Běžné zaokrouhlení se provádí funkcí round(), má 3 parametry:
- Zaokrouhlované číslo
- Nepovinný: Přesnost (na kolik desetinných míst)
- Nepovinný: Půlící hodnota (od jaké hodnoty se má zaokrouhlovat nahoru)
round(5); // 5
round(5.1); // 5
round(5.4); // 5
round(5.5); // 6
round(5.8); // 6
round(5483.47621, 2); // 5483.47
round(5483.47621, -2); // 5500
Dále existuje funkce floor() pro zaokrouhlení směrem dolů a funkce ceil() pro směr nahoru.
Pozor na datové typy!
Všechny zaokrouhlovací funkce vrací výsledek jako
float
a to i v případě, že je výsledkem celé číslo.Pokud chceme s výsledkem pracovat jako s celým číslem, je důležité ho ještě dodatečně přetypovat. Například:
echo (int) round(3.14);
PHP pracuje s různými datovými typy, například u floatu se může snadno stát, že výsledkem funkce round()
nebude číslo s konečným desetiným rozvojem. Pro výpis doporučuji použít funkci number_format()
, o které pojednávám níže.
Goniometrické funkce
Používají se na hodně různých výpočtů a vychází z jednotkové kružnice. Využití je například při vykreslování kružnic, elips, posunů a podobně.
Cyklometrické funkce
Výpočet úhlu z x
a y
. Převody kartézských a polárních souřadnic.
Hyperbolické funkce
Vychází z jednotkové hyperboly. Jejich definice lze jednoduše popsat pomocí přirovnání:
- Elipsa, Kružnice, Kružnice s poloměrem 1
- Hyperbola, Rovnoosá hyperbola, Jednotková hyperbola
Používají se například při generování terénu a fyzikální simulace.
Hyperbolometrické funkce
Vychází z jednotkové hyperboly.
Příklady použití goniometrických funkcí
echo sin(30); // -0.98803162409286
echo sin(deg2rad(30)); // 0.5
echo cos(deg2rad(123)); // -0.54463903501503
echo 1/tan(deg2rad(45)); // 1 (onen cotangens)
echo sin(deg2rad(500)); // 0.64278760968654
echo atan2(deg2rad(50), deg2rad(23)); // 1.1396575860761
Kalkulačka - zpracování matematického výrazu
Někdy se může stát, že budeme potřebovat zpracovat matematický výraz jako uživatelský řetězec, tedy třeba 5+2^(1+3/2)
.
V PHP neexistuje jednoduchý způsob, jak takový vstup zpracovat, ale naprogramoval jsem sérii knihoven, které tuto problematiku řeší.
Podrobnosti si přečtěte v samostatném článku Kalkulačka v PHP: Zpracování matematického výrazu jako řetězec.
Operace s velkými čísly a přesnost výpočtů
Velká čísla a desetinná čísla se v PHP ukládají jako float, navíc se zaokrouhlují přibližně na 15 desetinných míst, což může být někdy nepříjemné. Proto vznikla knihovna BCMath Arbitrary Precision Mathematics.
Čísla se v této knihovně reprezentují jako string, proto nejsou limitovány nepřesností floatu, nicméně prováděné operace jsou o několik řádů pomalejší (ale stále jde o rychlejší způsob, než kdybychom si takovou funkci naprogramovali sami).
Pokud chceme získat například odmocninu ze 2 na 3 desetinná místa, tak stačí jen zavolat:
echo bcsqrt('2', 3); // 1.414
Jan Barášek Více o autorovi
Autor článku pracuje jako seniorní vývojář a software architekt v Praze. Navrhuje a spravuje velké webové aplikace, které znáte a používáte. Od roku 2009 nabral bohaté zkušenosti, které tímto webem předává dál.
Rád vám pomůžu:
Kontakt Spolupráce