7. Čísla a číselné sústavy

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.))


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).