Převod do soustav
1. PrevodDoSoustav
1.1. Analýza a návrh řešení
V matematice dnes běžně používáme desítkovou soustavu. Jak již sám název napovídá, tato soustava obsahuje 10 prvků: číslice 0 ÷ 9. Tato soustava však není jedinou soustavou, kterou lze využít. Další soustavou je např. šedesátková soustava. Takovou soustavu využíváme pro měření minut, nebo sekund, kde časový okamžik lze zapsat jako údaj o třech číslicích - hodiny : minuty : sekundy.
V oblasti informatiky se využívají různé soustavy např. dvojková, osmičková, šestnáctková.
Celá čísla jsou vyjádřena posloupností 0 a 1 ve dvojkové soustavě. Při převodech mezi soustavami se vychází ze skutečnosti, že každé celé číslo lze vyjádřit polynomem mocnin základu číselné soustavy. Tedy:
kde:
- d ... základ číselné soustavy (např. 2, 8, 10, 16)
- i ... řád
- p ... počet číslic
- ci ... jednotlivé číslice
Př.:
V desítkové soustavě:
1234 = 1*103 + 2*102 + 3*101 + 4*100
Ve dvojkové soustavě:
1234 = 1*210 + 0*29 + 0*28 + 1*27 + 1*26 + 0*25 + 1*24 + 0*23 + 0*22 + 1*21 + 0*20
V našem příkladu budeme konvertovat číslo z desítkové soustavy do:
- Dvojkové (binární) soustavy - obsahuje 2 prvky: číslice 0 a 1. Hodnota vyjádřená v této soustavě je tedy rozepsána do jednotlivých pozic (bitů - bit je značen b), kde každá pozici obsahuje 0, nebo 1. Se zvyšováním počtu pozic, roste i možná hodnota, kterou lze uložit. 1 Byte (značen B) obsahuje 8 bitů, tedy 8 pozic. Na 1 B, tedy existuje 256 různých kombinací, protože 28=256. Následující obrázek ukazuje princip převodu čísla 90 v desítkové soustavě - označme jej následujícím způsobem (90)10 do dvojkové soustavy (?)2 - viz Obrázek 1. Podstatou je využití celočíselného dělení čísla 90 v desítkové soustavě základem soustavy, do které chceme převádět, v našem případě základu 2. Dále je využita operace zbytku po celočíselném dělení. Díky tomu získáme hodnoty, které přepíšeme odzadu. Tím získáme číslo zapsané ve dvojkové soustavě (1011010)2.

Obrázek 1: Princip převodu čísla z desítkové do dvojkové soustavy

- Šestnáctkové (hexadecimální) soustavy - obsahuje 16 prvků: číslice 0 ÷ 9 a písmena, která vyjadřují zbytek větší než 9, tzn. A (pro číslo 10), B(11), C(12), D(13), E(14) a F(15). Na následujícím obrázku je znázorněn princip převodu čísla z desítkové do šestnáctkové soustavy - viz Obrázek 3. Jak vidíme, je využit ten samý princip převodu jako u dvojkové soustavy s tím rozdílem, že základ (dělitel) je v tomto případě hodnota 16. U zbytku, který je větší než hodnota 9, je zbytek nahrazen písmeny, v našem případě je číslice 10 nahrazena písmenem A.

Obrázek 3: Princip převodu čísla z desítkové do šestnáctkové soustavy
Pro zpětný převod je znovu využito předchozího principu. Zde však sčítáme hodnoty vzniklé násobením hodnot na všech pozicích násobených společným základem 16, který je však umocněn příslušným řádem. Namísto písmen dosazujeme příslušné celočíselné hodnoty.

Obrázek 4: Princip převodu čísla z šestnáctkové do desítkové soustavy
Zkusme si nyní popsat algoritmus PrevodDoSoustav zaznamenaný pomocí vývojového diagramu - viz Obrázek 5. V hlavním program je deklarována proměnná n, do které je uloženo číslo z desítkové soustavy, které má být konvertováno do dvojkové nebo šestnáctkové soustavy. V hlavním programu je volán podprogram (funkce) Prevod, který navrací konvertované vstupní číslo n v podobě textového řetězce reprezentující číslo ve vybrané soustavě.

Obrázek 5: Hlavní program PrevodDoSoustav pro konverzi čísel z desítkové soustavy do dvojkové, nebo šestnáctkové soustavy
Funkce Prevod zajišťuje konverzi formálního parametru n, který reprezentuje číslo v desítkové soustavě. V této funkci jsou deklarovány následující proměnné:
- p ... počet bitů
- c ... zbytek po celočíselném dělení
- d ... dělitel (základ soustavy)
- i ... pozice bitu ve výstupním textu
- s ... výstupní text (převedené číslo)
- soustava ... index vybrané soustavy
Prvním krokem je inicializace textového řetězce s, do něhož budou postupně ukládány číslice (konvertovaná čísla), nebo také písmena (pokud bude prováděn převod do šestnáctkové soustavy). U podprogramu musíme zajistit validaci zvoleného typu soustavy. Ta je realizována pomocí cyklu s podmínkou na konci, v jehož těle se nachází příkazy pro výpis výzvy k výběru typu soustavy pomocí indexu (0 ... dvojková soustava, 1 ... šestnáctková soustava) a zároveň příkaz načtení hodnoty indexu do proměnné soustava. Pokud uživatel nezadá validní index, nedojde k opuštění cyklu a uživatel musí vybrat typ soustavy znovu.
Další cyklus s podmínkou na konci slouží k validaci počtu bytů zvolené uživatelem. Uživatel může zadat pouze některou z přípustných variant čísel 1, 2, 4, nebo 8. Tyto hodnoty představují počet bytů, tj. 1 B, 2 B, 4 B, nebo 8 B. Tato hodnota určuje maximální hodnotu, kterou lze uložit. Pokud bude rozsah překročen, nastane tzv. přetečení. Pokud uživatel zadá jiný počet bytů, proběhne znovu cyklus, který zahrnuje výpis a načtení hodnoty do proměnné p. Do proměnné p je pouze dočasně uložena hodnota počtu bytů, kterou následně využijeme pro určení celkového počtu pozic u jednotlivých soustav (rozhodování jakou soustavu uživatel zvolil je realizováno pomocí rozhodovací bloku s podmínkou soustava == 0). Do těchto pozic budeme zapisovat jednotlivé hodnoty zbytku po celočíselném dělení konvertovaného čísla základem soustavy (dělitelem) vypočítané v každé iteraci (tedy pro každé i značící řád). Procházení jednotlivých pozic (příslušného řádu) je realizováno pomocí cyklu s krokem - víme dopředu, kolik iterací má proběhnout. U dvojkové soustavy lze jeden 1 B zobrazit na 8 pozicích (8 bitech). U šestnáctkové soustavy nám však postačí pro 1 B pouze 2 pozice (lze ukládat i písmena). Po vypočtení zbytku po celočíselném dělení (hodnoty zapsané do jednotlivé pozice) musíme rozhodnout, zda zbytek je menší než hodnota 10. Je to z důvodu zapisování písmen namísto celočíselné hodnoty v případě šestnáctkové soustavy - musíme nahradit např. číslo 10 písmenem "A" (ve Flowgorithm nelze používat jednotlivé znaky, ale musí být použit textový řetězec - v C# budeme používat znaky - typ char např. 'A'). Jak ale zapsat do výsledného textového řetězce jednotlivé znaky?
Je více možností. První možností je např. využití konverze čísla na text pomocí ToString. Další možností je použití rozhodovací bloku, kde na základě hodnoty, kterou porovnáváme v podmínce, doplníme příslušnou číslici do výsledného textového řetězce. My však využijeme chytřejšího principu. Budeme používat jednotlivé číslice a znaky uložené v ASCII tabulce. Na pozici 48 se v tabulce ASCII nachází číslice '0'. Na pozici 49 se nachází číslice '1', atd. Tyto dvě číslice využijeme jak ve dvojkové, tak v šestnáctkové soustavě. Ostatní číslice a písmena budou vyžita pouze v šestnáctkové soustavě. Ve Flowgorithm pro účely vyhledávání znaku na určité pozici, nebo návratu pozice určitého znaku využijeme dvou příkazů:
- ToChar(c) - provádí konverzi kódu znaku uloženého v celočíselné proměnné c na znak, tj. navrátí znak nacházející se na celočíselné pozici c v tabulce ASCII
- ToCode(q) - provádí konverzi znaku uloženého v proměnné q (textovém řetězci) na kód znaku, tj. navrátí celočíselnou pozici znaku q v tabulce ASCII
Následující přiřazení znaku na určitou pozici provedeme pomocí příkazu (platí pro konverzi celočíselné hodnoty uložené v c na číslici):
s = ToChar(c + ToCode("0")) & s
kde:
- ToCode("0") ... návrat pozice číslice "0" v ASCII → číslo 48
- c + ToCode("0") ... na kterou pozici (hodnota v c) se máme posunout
- ToChar(c + ToCode("0")) ... návrat číslice (znaku), která se se nachází na pozici, na kterou jsme se posunuli, např. hodnota vypočteného zbytku po celočíselném dělení je rovna jedné, tzn. c = 1 → ToChar(49) ... návrat číslice "1"
- např. ToChar(49) & s ... připojení číslice "1" zleva ke stávajícímu textovému řetězci s
- např. s = ToChar(49) & s ... přepsání starého řetězce uloženým v s novým, tj. stávající řetězec s připojenou číslicí "1"
Pokud byl vypočtený zbytek uložený v proměnné c větší než 9, musíme do stávajícího textového řetězce s připojit písmeno (platí pro konverzi celočíselné hodnoty uložené v c na písmeno):
s = ToChar(c - 10 + ToCode("A")) & s
kde:
- ToCode("A") ... návrat pozice znaku "A" v ASCII → číslo 65
- c -10 ... o kolik pozic se máme posunout od čísla 10 (číslo 10 představuje písmeno "A")
- (c -10 + ToCode("A") ... o kolik pozic se máme posunout od písmene "A" (pokud je zbytek po celočíselném dělení větší než 9, např. c = 11, musí být za něj dosazeno písmeno "B". Toto písmeno je o jednu pozici za písmenem "A", tzn. c - 10 = 11-10 = 1 ... písmeno "B" je o 1 pozici za "A"
- např. ToChar(66) & s ... připojení písmene "B" zleva ke stávajícímu textovému řetězci
- např. s = ToChar(66) & s ... přepsání starého řetězce uloženým v s novým, tj. stávající řetězec s připojeným písmenem "B"
Kvůli vizuálnímu oddělení jednotlivých částí textového řetězce je použita podmínka, kde za každé 4 pozice je do textového řetězce vložena mezera.
Pro další iteraci (další řád) musí být vypočtena nová hodnota konvertovaného čísla pomocí celočíselného dělení konvertovaného čísla základem soustavy, tj. pomocí příkazu n = n / d.
Pokud jsme provedli zápis hodnot na všech pozicích a stále nám zbývá v proměnné n nějaká hodnota, tj. n > 0, znamená to, že jsme chtěli do čísla v soustavě uložit větší hodnotu, než je schopno pojmout (rozsah proměnné záleží na zvoleném počtu bytů). Jedná se o tzv. přetečení.
Návratem funkce je výsledný textový řetězec. Podstata popisovaného principu je znázorněna v následujícím vývojovém diagramu - viz Obrázek 6.
Obrázek 6: Podprogram Prevod - funkce pro konverzi celého čísla z desítkové soustavy do zvolené soustavy (dvojkové, nebo šestnáctkové)

