V poslednej kapitole tejto časti učebnice sa budeme venovať práci s číslami a číselnými sústavami. Najprv si naprogramujeme obľúbenú hru Hádaj číslo a potom si naprogramujeme program, ktorý bude prevádzať čísla z dvojkovej sústavy do desiatkovej a naopak.
Hádaj číslo:
Pri tejto úlohe využijeme vedomosti z predchádzajúcich kapitol. Vytvoríme si prázdnu triedu, pomenujeme si ju a prepojíme s triedou Konzola.
public static void main(String[] args)
{
String s; // deklarácia reťazca s
do { // vonkajší cyklus, ktorý zabezpečuje vygenerovanie náhodného čísla a spustenie samotného hádania
int r = (int)náhodnéCeléČíslo(1, 50); // Program vygeneruje náhodne číslo od 1 do 50 a priradí ho do premennej r
int c = 0, n, h[] = new int[20]; // ????
do { // vnútorný cyklus, ktorý zabezpečuje načítanie jednotlivých pokusov používateľa a porovnanie, či uhádol vygenerované číslo
n = (int)načítajCeléČíslo("Hádaj číslo od 1 do 50"); // do premennej n načítavame číslo, ktoré zadá požívateľ (jednotlivé pokusy používateľa)
if (n > r) // ak je hodnota premennej n väčšia ako hodnota premennej r – porovnanie pokusu s vygenerovaným číslom
{
System.out.println("Menej..."); // výpis na obrazovku
}
else // vetva else
{
if (n < r)
{
System.out.println("Viac...");
}
}
if (c < 20) // podmienka, ktorá zabezpečí zapamätanie si pokusov hádania ak ich je menej ako 20
{
h[c] = n; // zapamätanie si hádaných čísel
}
++c; // zvýšenie c o jedna po každom vykonaní cyklu do-while, kým je splnená koncová podmienka
} while (r != n); // podmienka na konci cyklu, ktorá ukončuje cyklus vo chvíli, keď nie je splnená – teda vtedy, keď r rovná sa n, v takom prípade program pokračuje vetvou switch; v tomto prípade je dobré použiť cyklus s podmienkou na konci, pretože takto ľahko zabezpečíme načítanie pokusov od používateľa a zároveň ak hneď pri prvom pokuse uhádne rovno pokračujeme vetvou switch
switch (c) // zabezpečenie výpisu na koľký pokus používateľ uhádol hádané číslo
{
case 1: System.out.println("Uhádol si na prvý pokus!"); break;
case 2: System.out.println("Uhádol si na druhý pokus!"); break;
case 3: System.out.println("Uhádol si na tretí pokus!"); break;
case 4: System.out.println("Uhádol si na štvrtý pokus."); break;
case 5: System.out.println("Uhádol si na piaty pokus."); break;
default: System.out.println("Potreboval si: " + c + " pokusov");
}
if (c < 20) // podmienka ak c je menšie ako 20 používateľovi vypíše všetky jeho pokusy
{
System.out.print("A takto si hádal: ");
for (int i = 0; i < c - 1; ++i) // for cyklus, ktorý nám zabezpečí postupný výpis všetkých hádaných čísel
{
System.out.print(h[i] + ", ");
}
System.out.println(h[c - 1] + ".");
}
else // vetva else, ktorá zariadi výpis posledných 20-tich pokusov
{
System.out.print("Toto bolo tvojich prvých dvadsať pokusov: ");
for (int i = 0; i < 19; ++i)
{
System.out.print(h[i] + ", "); // výpis čísel
}
System.out.println(h[19] + "."); // výpis posledného 20-teho hádaného čísla
}
s = načítajReťazec("Ešte raz?"); // možnosť zahrať si hru odznova
} while (s.equalsIgnoreCase("áno") || s.equalsIgnoreCase("ano") ||
s.equalsIgnoreCase("á") || s.equalsIgnoreCase("a")); // pri akejkoľvek z týchto štyroch možností sa program spustí ešte raz a používateľ znova háda náhodne vygenerované číslo
System.out.println("Koniec."); // výpis, že hra sa skončila
}
Ako z programu vidíme, na to aby správne fungoval ho potrebujeme prepojiť s triedou Konzola.
Prevod z binárnej sústavy do desiatkovej a naopak:
Skôr ako vytvoríme samotné programy vysvetlíme si na akom princípe fungujú prevody medzi pozičnými číselnými sústavami.
Pozičné číselné sústavy sú sústavy pozostávajúce z určitého počtu cifier (v desiatkovej ich je desať 0 – 9), ktoré sú usporiadané do pozícií, ktoré sa tiež nazývajú rády. Tá istá cifra umiestnená na inom ráde má inú hodnotu. Rády sú číslované sprava doľava od 0 vyššie, pretože prvá cifra sprava má najmenšiu hodnotu. V desiatkovej sústave posunutím cifry o jedno miesto (rád) doľava, cifra nadobudne desaťkrát väčšiu hodnotu. V dvojkovej sústave posunutím cifry o jeden rád doľava, cifra bude mať dvakrát väčšiu hodnotu.
Prevod čísel do desiatkovej sústavy: Očíslujeme si rády čísla, t.j. pod prvú cifru sprava napíšeme 0 pod druhú 1 pod tretiu 2…
Výsledné číslo v desiatkovej sústave potom dostaneme ako súčet cifier vynásobený základom sústavy na príslušný rád. Tento postup funguje pre všetky sústavy.
Prevod čísel z desiatkovej do inej sústavy:
215 : 2 = 107; 107 : 2 = 53; 53 : 2 = 26; 26 : 2 = 13; 13 : 2 = 6; 6 : 2 = 3; 3 : 2 = 1; 1 : 2 = 0
zvyšok 1 zvyšok 1 zvyšok 1 zvyšok 0 zvyšok 1 zvyšok 0 zvyšok 1 zvyšok 1 Výsledok teda je 11010111 (zvyšky zapísané v opačnom poradí, t.j od konca).
A takto rovnaké číslo 215 prevedieme do šestnástkovej sústavy. 215 : 16 = 13; 13 : 16 = 0; zvyšok 7 zvyšok 13 (to zodpovedá symbolu D – symboly sú ABCDEF, kde A = 10, B = 11, C = 12, D = 13, E = 14, F = 15) Výsledok je teda D7.
Prevody medzi sústavami: Pri prevode celých čísel z jednej do druhej pozičnej sústavy sa používajú algoritmy postupným delením, pričom využívame vzťahy medzi ich základmi – 8 = 23 resp. 16 = 24, ak združíme cifry binárneho čísla do trojíc resp. štvoríc a tie vyjadrime v desiatkovej sústave, vznikne číslo v osmičkovej, resp. šestnástkovej sústave.
Najprv si vytvoríme príklad na prevod z desiatkovej sústavy do dvojkovej, bude prepojený s Konzolou a využijeme metódy jazyka Java.
Algoritmus vyzerá nasledovne:
public static void main(String[] args)
{
int i = (int)načítajCeléČíslo("Zadaj číslo v desiatkovej sústave");
String binstr = Integer.toBinaryString(i); //metóda na prevod do binárnej sústavy
System.out.print("v dvojkovej sústave to je:" + binstr);
}
Program na prevod z dvojkovej sústavy do desiatkovej má rovnakú filozofiu. Podstatný rozdiel je ale v tom, že nenačítavame číslo (aj keď na prvý pohľad sa nám to tak zdá), ale načítavame reťazec znakov.
public static void main(String[] args)
{
String c = načítajReťazec("Zadaj číslo v dvojkovej sústave");
System.out.print("V desiatkovej sústave je to číslo:" + Integer.parseInt(c,2)); // výpis čísla a jeho prevod
}
Úlohy na precvičenie:
Prevod čísla zo šestnástkovej sústavy do desiatkovej: Napíšte program, ktorý zadané číslo prevedie zo šestnástkovej do desiatkovej sústavy.
(Tip: Skúste využiť cyklus for. Zadané číslo bude programom spracovávané po jednotlivých znakoch. Pre každý znak zadaného čísla (v šestnástkovej sústave) zistí jeho hodnotu v desiatkovej sústave. Pre prácu so znakmi použite údajový typ char. Pre priradenie znaku na pozícii i z reťazca názovReťazca do premennej znakNaPoziciiI použite zápis: char znakNaPoziciiI = názovReťazca.charAt(i); Aby sme vedeli koľkokrát treba zopakovať cyklus for, musíte zistiť dĺžku zadaného reťazca. Dĺžku zadaného reťazca vracia metóda: názovReťazca.length(); Ďalej použite vetvenie switch pre rozlíšenie jednotlivých prípadov spracovávaného znaku (skupiny 0-9 a a-f).
Java automaticky chápe znak (údajový typ char) ako číslo – jeho poradie v UNICODE tabuľke. Skupiny znakov '0'..'9','a'..'f' a 'A'..'F' sú v tabuľke za sebou, s pomocou ich poradových čísel im potrebujeme priradiť hodnoty 0..15. Pre každú zo skupín (0-9, a-f, A-F) vždy odčítame prvý znak skupiny od daného znaku, výsledný rozdiel určuje hľadanú hodnotu znaku. Okrem skupiny 0-9 vždy pripočítavame k rozdielu čísel číslo 10, pretože znaky a-f majú v desiatkovej sústave hodnoty 10-15.
Po každom vykonaní for cyklu, musíte čiastkový výsledok vynásobiť 16, pretože ide o posun rádu v šestnástkovej sústave. (V desiatkovej napr.: pri čísle 12 by sme mali čiastkový výsledok po prvom prebehnutí cyklu 1 a ten by sme násobili 10-kou aby sme sa posunuli o ďalší rád vyššie.))
Odpoveď:
public static void main(String[] args)
{
String hex = načítajReťazec("Zadaj číslo v šestnástkovej sústave");
int k, vysledok = 0;
for (int i = 0; i < hex.length(); i++) // pre každý znak reťazca hex rob:
{
char znak = hex.charAt(i); // do premennej znak ulož znak na i-tej pozícii v reťazci hex
switch(znak)
{
case('0'):
case('1'):
case('2'):
case('3'):
case('4'):
case('5'):
case('6'):
case('7'):
case('8'):
case('9'): k = znak - '0'; break; // pre skupinu číslic 0-9 uloží hodnotu čísla do pomocnej premennej k
case('a'):
case('b'):
case('c'):
case('d'):
case('e'):
case('f'): k = znak - 'a' + 10; break; // pre skupinu znakov a-f uloží do premennej k ich hodnotu v 16-kovej sústave
case('A'): // nasledujúce vetvy spracúvajú vstup zadaný veľkými písmenami
case('B'):
case('C'):
case('D'):
case('E'):
case('F'): k = znak - 'A' + 10; break;
default: k = 0;
}
vysledok = 16 * vysledok + k; // nastáva posun rádu – výsledok je sa vynásobí 16-timi a priráta sa k nemu hodnota posledného spracovaného znaku
}
System.out.println("Zadané číslo je v desiatkovej sústave číslo: " + vysledok);
}
Daj do správneho poradia:
Daj do správneho poradia časti kódu príkladu, ktorý vypíše opačné poradie cifier na vstupe zadaného čísla. Jednotlivé časti presúvaš pomocou myši do šedých políčok v spodnej časti, pričom ak si sa pomýlil, obrázok v spodnej časti môžeš vymeniť ak naň presunieš nový obrázok z vrchnej časti. Prerušovaná čiara oddeľuje časti kódu, ktoré je treba dať do správneho poradia (nad čiarou) a už usporiadanú časť kódu (pod čiarou).