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**.
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.
$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).
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)
.
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.
Běžné zaokrouhlení se provádí funkcí round(), má 3 parametry:
round(5); // 5round(5.1); // 5round(5.4); // 5round(5.5); // 6round(5.8); // 6round(5483.47621, 2); // 5483.47round(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.
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ě.
Výpočet úhlu z x
a y
. Převody kartézských a polárních souřadnic.
Vychází z jednotkové hyperboly. Jejich definice lze jednoduše popsat pomocí přirovnání:
Používají se například při generování terénu a fyzikální simulace.
Vychází z jednotkové hyperboly.
echo sin(30); // -0.98803162409286echo sin(deg2rad(30)); // 0.5echo cos(deg2rad(123)); // -0.54463903501503echo 1/tan(deg2rad(45)); // 1 (onen cotangens)echo sin(deg2rad(500)); // 0.64278760968654echo atan2(deg2rad(50), deg2rad(23)); // 1.1396575860761
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.
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:
Nabízím trénink vývojářů, konzultace, školení a analýzu návrhových vzorů. Osobně v Praze nebo online.
Napište mi, pokud si nevíte rady.
Lektor: Jan Barášek
Články píše Jan Barášek © 2009-2024 | Kontakt | Mapa webu
Status | Aktualizováno: ... | cs