Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Lekce 12 - Matematické funkce v jazyce C

V minulé lekci, Vícerozměrná pole v jazyce C, jsme si představili vícerozměrná pole.

V dnešním tutoriálu kurzu základů jazyka C se podíváme na standardní knihovnu math.h. Ta poskytuje velké množství funkcí pro řešení obvyklých matematických problémů, ty nejdůležitější z nich si uvedeme.

fmin(), fmax(), fdim()

Začněme s tím jednodušším :) Všechny funkce přijímají jako parametr dvě čísla typu double. Funkce fmin() vrátí to menší, funkce fmax() to větší z nich. Funkce fdim() vrátí x - y, je-li x > y. V ostatních případech vrací 0.

round(), ceil(), floor() a trunc()

Všechny funkce se týkají zaokrouhlování a přijímají parametry typu double. Návratová hodnota je pro všechny funkce rovněž typu double. round() vrací zaokrouhlené číslo tak, jak to známe ze školy (od 0.5 nahoru, jinak dolů). ceil() zaokrouhlí vždy nahoru a floor() vždy dolů. trunc() nezaokrouhluje, pouze odtrhne desetinnou část.

round() budeme jistě potřebovat často, další funkce jsem často použil například když jsem zjišťoval počet položek na stránce (např. nějaké tabulky v konzoli). Máme-li 33 položek a na stránce jich je vypsáno 10, budou matematicky zabírat 3.3 stránek. Výsledek musíme zaokrouhlit nahoru, protože v reálu stránky budou samozřejmě 4.

Pokud vás napadlo, že floor() a trunc() dělají to samé, chovají se jinak u záporných čísel. Tehdy floor() zaokrouhlí na číslo více do mínusu, trunc() zaokrouhlí vždy k nule.

Zaokrouhlení desetinného čísla a jeho uložení do proměnné typu int tedy provedeme následujícím způsobem:

double d = 2.72;
int a = (int)round(d);

Přetypování na int je nutné, jelikož round() vrací sice celé číslo, ale stále uložené v typu double a to kvůli tomu, aby všechny matematické funkce měly stejné rozhraní. Proto nebudu u zbylých funkcí typy uvádět - vždy bude double.

abs() a signbit()

abs() vrátí absolutní hodnotu parametru a signbit() vrátí 1, je-li číslo záporné, ve zbylých případech vrací 0. Funkce signbit() není podporovaná ve všech kompilerech, proto je možné, že ji nemusíte mít dostupnou.

sin(), cos(), tan()

Klasické goniometrické funkce přijímají jako parametr úhel v radiánech, nikoli ve stupních. Pro konverzi stupňů na radiány stupně vynásobíme hodnotou * (M_PI / 180).

acos(), asin(), atan()

Opět klasické cyklometrické funkce (arkus funkce), které podle hodnoty goniometrické funkce vrátí daný úhel. Jedná se o inverzní funkce k sin(), cos() a tan(). Parametrem je hodnota úhlu, výstupem úhel v radiánech. Pokud si přejeme mít úhel ve stupních, vynásobíme radiány hodnotou * (180 / M_PI).

pow() a sqrt()

pow() přijímá dva parametry, první je základ mocniny a druhý exponent. Pokud bychom tedy chtěli vypočítat např. 23, kód by byl následující:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main(int argc, char** argv)
{
    double vysledek = pow(2,3);
    printf("%lf", vysledek);
    return (EXIT_SUCCESS);
}

sqrt() je zkratka ze SQuare RooT a vrací druhou odmocninu z daného čísla.

exp(), log(), log10()

Funkce exp() vrací Eulerovo číslo, umocněné na daný exponent. Funkce log() vrací přirozený logaritmus daného čísla. log10() vrací dekadický logaritmus daného čísla.

V seznamu metod nápadně chybí libovolná odmocnina. My ji však dokážeme spočítat i na základě funkcí, které knihovna poskytuje.

Víme, že platí: 3. odm. z 8 = 8^(1/3). Můžeme tedy napsat:

double vysledek = pow(8, (1.0/3.0));
printf("%lf", vysledek);

Je velmi důležité, abychom při dělení napsali alespoň jedno číslo s desetinnou tečkou, jinak bude C předpokládat celočíselné dělení a výsledkem by v tomto případě bylo 8^0 = 1.

Dělení

Programovací jazyky se často odlišují tím, jak v nich funguje dělení čísel. Tuto problematiku je nutné dobře znát, abyste nebyli překvapeni. Napišme si jednoduchý program:

int a = 5 / 2;
double b = 5 / 2;
double c = 5.0 / 2;
double d = 5 / 2.0;
double e = 5.0 / 2.0;
int f = 5 / 2.0;
printf("a=%d b=%f c=%f d=%f e=%f f=%d", a, b, c, d, e, f);

V kódu několikrát dělíme 5 / 2, což je matematicky 2.5. Jistě ale tušíte, že výsledek nebude ve všech případech stejný. Troufnete si tipnout, co kdy vyjde? Zkuste to :)

Konzolová aplikace
a=2 b=2.000000 c=2.500000 d=2.500000 e=2.500000 f=2

Vidíme, že výsledek dělení je někdy celočíselný a někdy reálný. Přitom nezáleží pouze na datovém typu proměnné, do které výsledek ukládáme, ale na datovém typu čísel, které dělíme. Pokud je jedno z čísel desetinné, je výsledek vždy desetinné číslo. 2 celá čísla vždy vrátí celé číslo, dejte si na to pozor, např. když budete počítat průměr. Pro desetinný výsledek je nutné alespoň jednu proměnnou přetypovat na desetinné číslo.

int soucet = 10;
int pocet = 4;
double prumer = (double)soucet / (double)pocet;

Pozn.: Např. v jazyce PHP je výsledek dělení vždy desetinný. Až budete dělit v jiném programovacím jazyce než je C, zjistěte si, jak dělení funguje než jej použijete.

Zbytek po celočíselném dělení

V našich aplikacích můžeme často potřebovat zbytek po celočíselném dělení (tzv. modulo). U našeho příkladu 5 / 2 je celočíselný výsledek 2 a modulo 1 (zbytek). Modulo se často používá pro zjištění, zda je číslo sudé (zbytek po dělení 2 je 0) nebo když chcete zjistit odchylku vaší pozice od nějaké čtvercové sítě.

V céčku a obecně v céčkových jazycích (tzv. C-like jazyky) zapíšeme modulo jako %:

printf("Zbytek po deleni 5/2 je %d", 5 % 2);

Tak to bychom měli.

V následujícím cvičení, Řešené úlohy k 11. a 12. lekci Céčka, si procvičíme nabyté zkušenosti z předchozích lekcí.


 

Předchozí článek
Vícerozměrná pole v jazyce C
Všechny články v sekci
Základní konstrukce jazyka C
Přeskočit článek
(nedoporučujeme)
Řešené úlohy k 11. a 12. lekci Céčka
Článek pro vás napsal Patrik Valkovič
Avatar
Uživatelské hodnocení:
23 hlasů
Věnuji se programování v C++ a C#. Kromě toho také programuji v PHP (Nette) a JavaScriptu (NodeJS).
Aktivity