12. Operátory

Následující tabulka obsahuje aritmetický operátory, které jsou využívány při matematických operacích v C# – viz Tabulka 1. Ve vývojových diagramech jsme záměrně využívali ty samé operátory, aby náš přechod směrem od algoritmů ke zdrojovým kódům byl o něco lehčí.

Operátor

Operace

Příklad

+

Sečtení

x + y

-

Odečtení

x – y

*

Násobení

x * y

/

Dělení (celočíselné dělení)

x / y

%

Modulo – zbytek po celočíselném dělení

x % y

Tabulka 1: Aritmetické operátory

Pokud ukládáme do proměnné nějakou hodnotu výrazu, tento výraz se skládá z tzv. operandů (anglicky „Operand“ - např. z = x + y; kde x a y na pravé straně od operátoru přiřazení (operátor =) jsou operandy ve výrazu, tzn., že x + y je výraz). Nejprve je vypočtena hodnota výrazu na pravé straně a následně uložena do proměnné na levé straně.

Následující zdrojový kód ukazuje použití různých operátorů na celých číslech (datový typ int) – viz Kód 1.

//Deklarace celočíselné proměnné včetně inicializace
int x = 7;
//Deklarace celočíselné proměnné včetně inicializace
int y = 2;
 
//Provedení součtu celočíselných proměnných -> výsledek je 9
int soucet = x + y;
 
//Provedení rozdílu celočíselných proměnných -> výsledek je 5
int rozdil = x - y;
 
//Provedení součinu celočíselných proměnných -> výsledek je 14
int soucin = x * y;
 
//Provedení celočíselného dělení celočíselných proměnných -> výsledek je 3
int podilCelociselny = x / y;
 
//Provedení zbytku po celočíselného dělení celočíselných proměnných -> výsledek je 1
int zbytekPodilCelociselny = x % y;

Kód 1: Příklady aritmetických operací s celými čísly

Dbejte vždy zvýšené pozornosti na to, když jsou operandy různého datového typu. Pokud uvedeme příklad u celočíselného dělení, kde oba operandy budou celá čísla např. x = 5 / 2 do proměnné x bude uložena celočíselná hodnota 2. Pokud ale napíšeme x = 5 / 2.0, pak kompilátor C# detekuje nesoulad operandů a vygeneruje kód, který převede celé číslo (typ int) na reálné (typ double) před provedením aritmetické operace. Výsledek operace je pak reálná hodnota 2.5 (typ double).

Dále bychom také měli vědět, že výsledek dělení libovolného čísla nulou je nekonečno (to je mimo rozsah typů int, long a decimal). Uveďme vyhodnocení výrazu např. 5 / 0. Vyhodnocení způsobí chybu. Avšak datové typy double a float mají ve skutečnosti speciální hodnotu, která může představovat nekonečno. Pokud tedy přepíšeme operandy výrazu na 5.0 / 0.0 výsledek bude nekonečno (výjimkou z tohoto pravidla je hodnota výrazu 0.0 / 0.0). Obvykle, pokud vydělíte nulu nějakou hodnotou, výsledek je nula. Pokud ale vydělíte číslo nulou, výsledkem je nekonečno. Výraz 0.0 / 0.0 vede k paradoxu; hodnota musí být současně nula a nekonečno. C # má pro tuto situaci další zvláštní hodnotu zvanou NaN, což znamená, že není číslem – zkratka anglického „Not a Number“. Pokud tedy vyhodnocujete výraz 0.0 / 0.0, výsledkem je NaN.

NaN a Nekonečno se ovlivňuje výrazy. Pokud vyhodnocujete 10 + NaN, výsledkem je NaN, a pokud vyhodnocujete 10 + Nekonečno, výsledkem je Nekonečno. Hodnota výrazu Nekonečno * 0 je NaN. [6]

Dalším důležitým faktem u výrazů je přednost některých operátorů před jinými operátory, např. násobení má přednost před sčítáním.

Co ale pokud operátory mají stejnou přednost, např. násobení a dělení. Pak je výraz postupně vyhodnocen zleva doprava. Pokud potřebujeme některý operátor upřednostnit před jiným, můžeme použít systém závorek.

Následující zdrojový kód ukazuje použití různých operátorů na kombinaci celé (datový typ int) a reálné číslo (datový typ double) – viz Kód 2.

//Deklarace celočíselné proměnné včetně inicializace
int x = 7;
//Deklarace reálné proměnné (desetinné číslo) včetně inicializace
double z = 2;

//Provedení dělení celočíselné a reálné proměnné -> reálné číslo -> výsledek je 3.5
double podilRealny = x / z;
 
//Nelze provést dělení celočíselné a reálné proměnné, když výsledný typ je int -> K.O.
int podilRealny2 = x / z;
 
//Priorita operátorů -> výsledek je 26
int prioritaOperatoru1 = 2 * 3 + 4 * 5;
 
//Použití závorek pro upřednostnění operace -> výsledek je 70
int seZavorkami = 2 * (3 + 4) * 5;
 
//Priorita operátorů -> výsledek je 8
int prioritaOperatoru2 = 2 + 12 / 2;
 
//Použití závorek pro upřednostnění operace -> výsledek je 7
int seZavorkami2 = (2 + 12) / 2;

Kód 2: Příklady aritmetických operací s celým a reálným číslem

Jazyk C# umožňuje také zkrácení zápisu, tj. použití kombinace libovolného aritmetického operátoru s přiřazovacím operátorem. Tyto operátory se nazývají operátory složeného přiřazení (anglicky „Compound Assignment Operators“) - viz Tabulka 2. Výraz za přiřazovacím operátorem lze tedy zkrátit vypuštěním operandu se stejným názvem jako má proměnná na levé straně od operátoru přiřazení (proměnná, do které ukládáme hodnotu). Znamená to, že vypouštíme operand, který nám poskytuje informaci o aktuální hodnotě uložené v proměnné. U textového řetězce lze použít pouze operátor typu +=. 

Operátor

Standardní výraz

Zkrácený zápis výrazu

+

x = x + y;

x += y;

-

x = x – y;

x –= y;

*

x = x * y;

x *= y;

/

x = x / y;

x /= y;

%

x = x % y;

x %= y;

Tabulka 2: Operátory složeného přiřazení – zkrácený zápis výrazu

Jistě si vzpomínáte, že v cyklu s krokem byla definována tzv. řídící proměnná (nebo též čítač) včetně přírůstku (nebo také inkrementu). Čítač obecně bývá značen písmenem i a jeho zápis inkrementace by vypadal např. takto i = i + 1; .Tento zápis bychom mohli redukovat za pomoci použití operátoru složeného přiřazení, tj. i += 1; Pro inkrementaci proměnné o hodnotu 1 jazyk C# umožňuje použít zápis proměnné s připojením dvojité plus, tj. i++. Tento operátor je tzv. unární, což znamená, že má pouze jeden operand. Pro dekrementaci (snížení) o hodnotu 1 zase lze použít operátor dvojité mínus, tj. i--.

Podívejme se na následující kód, který provádí inkrementaci - viz Kód 3. V něm je provedena deklarace a inicializace proměnné. Další řádek kódu nám vypisuje hodnotu proměnné, na níž byla provedena inkrementace. Tento výsledek necháme vypsat v dalším příkazu pro výpis.

//Deklarace proměnné včetně inicializace
int i = 0;
//Výpis proměnné, kde byla provedena inkrementace o 1
Console.WriteLine("Inkrementace i: {0}", i++);
//Výpis aktuální hodnoty proměnné
Console.WriteLine("Inkrementace i: {0}", i);

Kód 3: Příklad postfixové inkrementace proměnné

Na následujícím výpisu v konzoli vidíme, že se stala menší zrada – viz Výstup programu - Kód 3. V prvním řádku se vypsala hodnota proměnné, aniž by byla provedena inkrementace o 1.

Inkrementace i: 0
Inkrementace i: 1

Výstup programu - Kód 3: Ukázka výsledku inkrementace

Tím, že jsme použili operátor ++ umístněný za proměnnou, jsme programu řekli, že má nejprve provést vypsání v konzoli a teprve až po vypsání zvednout hodnotu proměnné o 1 (v kódu se postupovalo zleva doprava, jak jsme zvyklí). Použili jsme tzv. postfixový zápis. Pokud bychom potřebovali, aby se nejprve vypsala hodnota zvýšená o 1, musíme použít prefixový zápis, tzn. operátor umístit před proměnnou – viz Kód 4.

//Deklarace proměnné včetně inicializace
int i = 0;
//Výpis proměnné, kde byla neprve provedena inkrementace o 1
Console.WriteLine("Inkrementace i: {0}", ++i);
//Výpis aktuální hodnoty proměnné
Console.WriteLine("Inkrementace i: {0}", i);

Kód 4: Příklad prefixové inkrementace proměnné

Na následujícím výpis v konzoli vidíme, že už vše funguje tak, jak požadujeme – viz Výstup programu - Kód 4. V prvním řádku se vypsala hodnota proměnné, kde byla provedena inkrementace o 1. 

Inkrementace i: 1
Inkrementace i: 1

Výstup programu - Kód 4: Ukázka výsledku prefixové inkrementace 

A co to vše znamená? Jednoduchou poučku, vždy je nutné sledovat pořadí operandu a operátoru. Operátory inkrementace a dekrementace jsou zejména využívány v cyklech.

Na závěr této kapitoly si pojďme vyjmenovat prioritu jednotlivých skupin operátorů, podle toho, jak budou v C# postupně vykonávány – viz Tabulka 3.

Priorita (řazeno sestupně)

Skupina

Operátor

1

Primární

(), ++, -- (tj. Postfixový inkrement/dekrement)

2

Unární

!, +, -,++,--

3

Multiplikativní

*, /,%

4

Aditivní

+, -

5

Relační

<, <=, >, >=

6

Rovnost

==, !=

7

Podmínkové

&&, ||

8

Přiřazení

=

Tabulka 3: Operátory – priorita vykonávání