8. díl - Binární operace

C++ Pokročilé konstrukce v C++ Binární operace

Počítač pracuje v soustavě dvojkové. Jsou pouze 2 stavy (0/1), kterých může jeden vstup nabývat. Obecně můžeme stavy 0/1 převést na false (0) a true (1) - Celý počítač můžeme postavit na principu Booleovy algebry (část oboru matematické logiky). Booleova algebra disponuje dvěma stavy (true a false) a sadou několika funkcí, díky kterým můžeme vyjadřovat různé podmínky a závěry. V dnešním článku si jednotlivé funkce projdeme, řekneme si, jak jsou v C++ implementované a jak lze s nimi pracovat.

Logické funkce

Logická funkce zpravidla přijímá dva vstupy a má jeden výstup. Vstupy i výstup jsou hodnoty 0/1 neboli true/false. Pro článek projdeme pouze funkce, které jsou dostupné v C++. Každou funkci můžeme určit tabulkou pravdivostních hodnot. Tabulka bude mít stejný počet vstupů jako má funkce, a navíc sloupeček udávající výstupní hodnotu. Za seznamem jednotlivých funkcí je uvedena tabulka a jsou do ní zaneseny všechny probírané funkce.

AND

And neboli logický součin. Jedná se o funkci, která je pravdivá pouze v případě, kdy jsou pravdivé oba vstupy. Obvykle použijeme při kontrole, zda je splněna nějaké předem daná podmínka. V C++ zapisujeme symbolem binární ekvivalenci ampersandu (&).

OR

Or neboli logický součet. Funkce je pravdivá v případě, že je alespoň jeden ze vstupů pravdivý. Obvykle se používá ke zjištění, zda je nějaká sada vstupů nastavena. V C++ zapisujeme binární ekvivalenci svislítkem (|).

XOR

Xor neboli exkluzivní or. Jak už název napovídá, funkce je velmi podobná logickému součtu. Jediný rozdíl je v situaci, kdy jsou oba vstupy pravdivé. Xor vrátí 0 (false), zatímco or vrátí 1 (true). Proto je xor označen jako exkluzivní or - musí být pravdivý pouze jeden ze vstupů, nesmí být oba. V C++ značíme binární ekvivalenci stříškou (^)

NOT

Not neboli negace je velmi jednoduchá funkce, která vrací opak vstupu. Je-li vstup pravdivý, funkce vrátí 0 (false). Při nepravdivém vstupu je návratová hodnota 1 (true). V C++ značíme binární ekvivalenci vlnovkou (~).

Nakonec uvádím tabulku pravdivostních hodnot, kde "a" a "b" jsou vstupy.

a b AND OR XOR NOT
1 1 1 1 0 0 0
1 0 0 1 1 0 1
0 1 0 1 1 1 0
0 0 0 0 0 1 1

Chování logiky v C++

V C++ se můžeme setkat s logikou například u podmínek nebo cyklů. Operace se vždy převede na pravdivostní hodnotu. C++ má typ bool, který představuje pravdivostní hodnotu.Kromě toho jakoukoliv nenulová hodnota je považována za true. Pouze 0 je v C++ false. Při přetypování bool na číslo získáme 1, pokud byla hodnota true a 0, pokud byla hodnota false.

Určitě jste se divili, proč u každé funkce explicitně říkám "binární ekvivalence". C++ totiž standardně rozlišuje operace logické a binární. Logické operace již známe, běžně je používáme u podmínek (&&, ||, !). Binární operace pracují s celým číslem jako sekvencí bitů. Při aplikování binární operace se logické operace aplikuje pro každý bit v čísle. Před dalším čtením doporučují přečíst článek o převádění mezi soustavami.

Budeme-li pracovat pouze s čísly 1 a 0, budou logické a binární operace ekvivalentní. Pracujeme-li i s jinými čísly, výsledek se může lišit. To koneckonců ukazuje následující program:

int main()
{
cout << "5 > 4 = " << ( 5 > 4 ) << endl; //true
cout << "5 < 4 = " << ( 5 < 4 ) << endl; //false
if( 1 ) cout << "1 je vhodnoceno jako true" << endl;
if( 5 ) cout << "5 je vhodnoceno jako true" << endl;
if( 0 ); else cout << "0 je vyhodnoceno jako false" << endl;
if( !0 ) cout << "!0 je vyhodnoceno jako true" << endl;
cout << "5 && 4 = " << ( 5 && 4 ) << endl; //logický AND
cout << "5 & 4 = " << ( 5 & 4 ) << endl; //binární AND
cout << "5 || 4 = " << ( 5 || 4 ) << endl; //logický OR
cout << "5 | 4 = " << ( 5 | 4 ) << endl; //binární OR
cout << "!5 = " << !5 << endl;//logická negace
cout << "!0 = " << !0 << endl; //logická negace
cout << "~5 = " << ~5 << endl; //binární negace
cout << "5 ^ 4 = " << ( 5 ^ 4 ) << endl; //binární XOR
cout << "(5 ^ 4) && 0 = " << ( ( 5 ^ 4 ) && 0 ) << endl;
}

Výsledek:

Logické operace v C++

Dopuručuji si příklady pořádně projít. Logické a binární operace nepracují stejně, ale lze je kombinovat (jak předvádí poslední výstup). K tomuto tématu se ještě jednou vrátíme v příštím článku, kde si představíme tzv. bitové flagy.

Bitový posun

Existuje ještě jedna operace, která nemá základ v logických operacích. Jedná se o tzv. bitový posun. Nejprve si představíme číslo jako bitové pole. Posunem rozumíme takovou operaci, kdy se všechny bity přesunou o stejný počet míst. Bity, které vypadly z pole zahodíme a bity, které nám nyní chybí, doplníme nulami. Představme si číslo o velikosti 1 bajt reprezentované v binární soustavě. Bitové posuny se chovají následujícím způsobem:

10010111 => 00101110    //bitový posun o jedno místo vlevo
10010111 => 10111000    //bitový posun o tři místa vlevo
10010111 => 01001011    //bitový posun o jedno místo vpravo
10010111 => 00010010    //bitový posun o tři místa vpravo

V C++ značíme bitový posun dvěma šipkami. Současně se za šipky přidává index, o kolik se má číslo posunout. Příklad výše by byl v C++ zapsán následovně:

0b10010111 << 1 == 0b00101110   //bitový posun o jedno místo vlevo
0b10010111 << 3 == 0b10111000   //bitový posun o tři místa vlevo
0b10010111 >> 1 == 0b01001011   //bitový posun o jedno místo vpravo
0b10010111 >> 3 == 0b00010010   //bitový posun o tři místa vpravo

Pozn. autora: Předpona 0b znamená, že je číslo zapsané v binární podobě. Tato konstrukce není podporovaná u všech kompilátorů. MSVC, který je nainstalován ve Visual Studiu, tuto podobu čísla akceptuje.

Bitový posun je ekvivalentní s operací dělení (nebo násobení) čísla mocninou 2. Na rozdíl od dělení (nebo násobení) je operace bitového posunu méně náročná na procesor (a je tedy rychlejší). Tím ovšem nechci říct, abyste od teď používali pro operace násobení a dělení bitové posuny. Kompilátory jsou již dnes dostatečně chytré na to, aby váš kód dokázali optimalizovat. Pokud tedy někde použijete operaci dělení číslem 2, je velmi pravděpodobné, že kompilátor operaci nahradí právě bitovým posunem.

cout << "0x26 >> 1 = 0x" << hex << (0x26 >> 1 ) << endl;  //bitový posun o jedno místo vpravo
cout << "0x26 >> 3 = 0x" << hex << (0x26 >> 3 ) << endl;  //bitový posun o tři místa vpravo
cout << "0x26 << 1 = 0x" << hex << (0x26 << 1 ) << endl;  //bitový posun o jedno místo vlevo
cout << "0x26 << 3 = 0x" << hex << (0x26 << 3 ) << endl;  //bitový posun o tři místa vlevo
cout << "14 / 2 = " << (14 >> 1 ) << endl;
cout << "32 / 8 = " << (32 >> 3 ) << endl;
cout << "3 * 2 = " << (3 << 1 ) << endl;
cout << "3 * 16 = " << ( 3 << 4 ) << endl;

Výsledek:

Bitove posuny v C++

Bitový posun můžeme využít například při extrahování barevných složek. Budeme vědět, že každá barva zabírá 1 bajt. Dále víme, že složky jsou poskládány jako RGBA (tedy červená, zelená, modrá, průhlednost). Potom hodnotu zelené složky získáme jednoduše:

int zelena = (barva << 8) >> 24.

Nyní byste měli být schopni pracovat s jednotlivými bity. Zatím ale nemáme nejmenší důvod něco takového dělat. To napravíme příště, kdy si řekneme o výčtových typech a bitových příznacích.


 

Stáhnout

Staženo 0x (11.47 kB)
Aplikace je včetně zdrojových kódů v jazyce C++

 

  Aktivity (2)

Článek pro vás napsal patrik.valkovic
Avatar
Věnuji se programování v C++ a C#. Kromě toho také programuji v PHP (Nette) a JavaScriptu.

Jak se ti líbí článek?
Ještě nikdo nehodnotil, buď první!


 


Miniatura
Předchozí článek
Konstantní hodnoty
Miniatura
Všechny články v sekci
Pokročilé konstrukce v C++
Miniatura
Následující článek
Výčtové typy

 

 

Komentáře

Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zatím nikdo nevložil komentář - buď první!