Accendo / Publikované

Číselné sústavy

Autor: Libor Bešenyi

            Konverzia medzi číselnými sústavami je pomerne jednoduchá! Stačí si čísla trocha obľúbiť a pri troške praxe pochopíme celý mechanizmus. Výhodou iných sústav je napr. istý spôsob kompresie dát. Koľko znakov ma základná ordinálna tabuľka (viac o ordinálnych číslach: http://www.devnet.sk/modules.php?name=News&file=article&sid=52 )? 255. Takže jednotlivé znaky sú reprezentované číslmi od 0 po 255. Vieme, že jeden znak je jeden bajt a bajt sa rovná ôsmim bitom...

            A čo s tým všetkým majú číselné sústavy? Veľmi veľa! Tak pozrime sa najprv, prečo je znakov 255 a prečo sa jeden znak vlastne rovná ôsmim bitom. Tak začneme od konca. Vieme, že bity nadobúdajú hodnotu 0 a 1. Jedná sa teda o binárnu sústavu. Je to najprimitívnejšia sústava z hľadiska výroby hardware, ktorá mohla byť použitá! Preto takto môže byť fyzicky informácia reprezentovaná elektrickým impulzom – existuje elektrický signál alebo nie (jedna / nula). V počiatkoch informatiky sa za základnú sústavu zvolila práve dvojková (binárna).

Ale teraz sa vráťme. Na počiatkoch sa istí páni programátori dohodli, že hlavná tabuľka znakov, bude obsahovať práve 256 kusov (0...255). Od tohto okamihu sa odvodili pojmy ako bajt a bit. Ako? Keďže vo svete počítačov sú dôležité jednotky a nuly, tak si vyjadrime číslo 255 v dvojkovej sústave (použijeme zatiaľ kalkulačku):

 

1 1 1 1 1 1 1 1

 

Áno, jedná sa o osem „jedničiek“. Každá jednička / nula bude bit a celý oktet (osem jedničiek) pomenujme bajt (s týmto súvisia aj pojmy ako maska, wildcard apod. v sieťach, viac: http://www.devnet.sk/modules.php?name=News&file=article&sid=62 ) Keď budeme teraz rôzne kombinovať v tomto oktete jednotky a nuly, získame čísla v rozmedzí 0 – 255, teda čísla, ktoré budú reprezentovať „index“ znaku v tabuľke znakov – ordinálnej tabuľke. V prvom odkaze nájdeme aj postup, ako pracovať / vypísať apod. túto tabuľku.

 

Takéto počiatky počítačov datujeme do obdobia našich starých rodičov, tak načo to vedieť v dobách Call of Duty? Totiž, veľa sa to vo fungovaní týchto pekelných strojov (počítače) nezmenilo, aj keď sa to na prvý pohľad nezdá. Taká ordinálna tabuľka stále existuje a tvorí jadro všetkého, na čo „klikneme“. Nevyužíva sa už síce ako primárna tabuľka znakov, pretože logicky, by neexistovali lokalizované znaky, ako slovenské litinkové písmená kombinované s dĺžňami, mäkčeňmi a pod. Toto je už iná téma, ale ordinálne znaky sa využívajú v programovaní...

Celé systémy sú založené práve na týchto znakoch. Ako je to možné? Pozrime sa na hocijaký binárny súbor (.EXE, .BIN, .DAT...) a rátajme, koľko znakov nájdeme... Isto do čísla 255 (nie všetky znaky však patria medzi „viditeľné“ sú napr. „riadiace“ systémové znaky, ako ESC).

 

Tu sa môže natískať zvláštna myšlienka – iná sústava ako tá „naša“, teda desiatková a programátorom „nutná“ dvojková zahŕňa všetko, čo musíme pre zvládnutie programovania vedieť. To však nie je pravda! Začínajúci programátori sa isto stretnú s problémom práce s binárnymi súbormi. Potrebujeme skopírovať súbor (.EXE) a nás napadá zdrojový súbor otvoriť ako textový, čítať znak za znakom (char) a kopírovať ho / ich do novovytvoreného súboru. Ale čo sa to nestane? Program nemusí takýto súbor skopírovať – na vine sú práve špeciálne systémové znaky, ktoré majú ordinálne číslo, ale nie sú „viditeľné“, lebo ani nemusia. Medzi takéto znaky môže patriť ukazovateľ konca textového riadku (tzv. EOLN), alebo konca súboru (tzv. EOF). Keďže sa nedá ku týmto znakom „klasický“ pristupovať tak teda ako? Môžeme ich chápať ako ordinálne čísla a tie kopírovať / zapisovať!

S týmto sa zasa stretli možno tí pokročilejší, ktorý potrebovali cez jednoduché knižnice vo Windowse preniesť binárne súboru cez sieť. Tu však nastáva iný problém – keďže tabuľka obsahuje znaky od 0 po 255 tak prenos takýmto spôsobom môže miestami zrásť až trojnásobne, pretože prenášané čísla sú bajty! Aby nám nevznikol chaos v číselnom rade, museli by sme čísla spájať do tripletov, teda ak máme číslo 66, musí to byť 066, lebo ordinálne čísla môžu dosiahnúť hodnoty až 255 (trojciferné číslo) a tak nasledujúca postupnosť čísel pri nedodržaní „tripletov“ by viedla ku katastrofe: 66101115 môžu byť čísla 66 101 115 alebo 6 6 10 111 5 alebo ... teda ak chceme prenášať 66,101,115 musíme vytvárať triplety: 066101115, ktoré sa dajú krásne rozdeliť po trojciferných číslach! Teraz chceme cez takýto sieťový systém preniesť súbor, ktorý obsahuje len 6 bajtov a to reťazec „Besenyi“. Získame ordinálne hodnoty, upravíme na triplety a máme reťazec, ktorý prenesieme bez problémov cez sieť (vlastne aj tento súbor by sme preniesli, neobsahuje žiaden špeciálny znak, ale ako programátor, robíme univerzálny prenos a nevieme, čo za pliagu bude užívateľ prenášať). Dostávame postupnosť: 066101115101110121105 – teda omnoho väčšiu ako samotný zdrojový text!

Práve tu sa bude hodiť znova konverzia, napríklad do šestnástkovej sústavy (do väčšej ako desiatkova – aby sa znižoval ciferný základ). Znova „rozmotajme“ triplety a hoďme ich do hexovej (šestnástková) sústavy: 42 65 73 65 6E 79 69. Nepodstatne sa reťazec skrátil, teda konkrétne o tretinu, pretože maximálne ordinálne číslo 255 sa dá vyjadriť v hexovej sústave ako FF – teda maximálny počet cifier je dva! Nespájame tak čísla do tripletov, ale do „dvojzávitnic“.

 

Tento príklad bol demonštračný. Článok je určený začínajúcim programátorom a tak sa nezaoberá jednotlivými metódami problému, ale pokúša sa čitateľa naviesť na inú ako „drevorúbačskú“ cestu programátora.

Prekladáme čísla z desiatkovej sústavy

            Pozrime sa na zúbok binárnej sústave. Majme číslo 2345 v desiatkovej sústave. Aby sme ho pohodlne (aj bez kalkulačky) konvertovali do dvojkovej sústavy musíme ho deliť práve dvojkou, ak nám vyjde desatine číslo, zaokrúhlime ho na dol a napíšeme si ako pomocný výpočet jedna (teda zvyšok ktorý môže nastať v dvojkovej sústave – iný zvyšok nikdy nenastane). Ak sa jedná o celé číslo, napíšeme na ten výpočet nulu. Delíme, pokiaľ sa nedostaneme na koniec a pomocný výpočet prepíšeme v opačnom poradí a získavame binárne číslo:

 

            A chceme pracovať v osmičkovej sústave? Tak budeme deliť práve ôsmimi! Tu však pozor, zvyšok môžu byť čísla práve 1 – 7, resp. žiadne číslo. Najprv si ukážme, ako taká osmičková sústava vyzerá, vypíšeme prvých 20 čísel:

 

Dec

Oct

Dec

Oct

0

0

10

12

1

1

11

13

2

2

12

14

3

3

13

15

4

4

14

16

5

5

15

17

6

6

16

20

7

7

17

21

8

10

18

22

9

11

19

23

Tabuľka 1 Výpis prvých čísel osmičkovej sústavy

            Osmičková sústava sa znakmi nelíši od desiatkovej, ale pozná len prvých osem číslic (tak ako dvojková len prvé dve) a to 0 .. 7. Pomaly si už hádam vytvárame univerzálny pohľad na čísla v sústavách.

            Ako však pracovať so zvyškami? Predstavme si, že chceme číslo 68 v desiatkovej sústave prekonvertovať do osmičkovej. Postupujeme rovnako, videlíme ho osmičkou. Zvyšok však dostaneme opetovným násobením celého čísla a odrátaním od základu. Možno to vyzerá komplikovane, ale pravda je opakom. Dá sa to jednoducho napísať aj takto: Koľko krát sa v danom čísle nachádza osmička? A koľko nám ešte ostáva? Teda osmička v 68 sa nachádza 8 krát. 8 * 8 sa rovná 64 a zvýšilo sa nám ešte 4 (68 – 64). V „našich“ ôsmych sa koľkokrát nachádza osem? Raz ale ak to podelíme, zvyšok je 0. Znova jednotku delíme ôsmimi a zaokrúhlime nadol. Zostáva konečná nula ale pri delení nastal zvyšok (samotná jednotka). Pomocný výpočet znova prečítame od konca a získavame číslo 104, ktoré je ekvivalentom decimálnej 64 v osmičkovej sústave. Ďalší príklad:

 

Vieme teda, že n-číselná sústava menšia ako desiatková sa skladá z „jej“ znakov, konkrétne o prvých n-1. Začíname uvažovať univerzálne. Teda sedmičková sústava sa bude skladať z číslic 0 – 6, deviatková 0 – 8 apod. Čo však so sústavami viac ako decimálna? Iste ste si všimli z horného textu, že nasledujúce číslice budú nahrádzať písmenka z abecedy. Jedenástková sústava bude stále „jednociferná“ na desiatkovom čísle 10 – pretože 10 nahradíme písmenkom A (desiatková na čísle je už dvojciferná, ako vidíme, skladá sa z čísel 1 a 0). Číslo jedenásť už bude dvojciferné aj v jedenástkovej sústave – zvyšujeme cifru o druhé najväčšie číslo a opakujeme až do ďalšej „desiatky“. Aké je to druhé najväčšie číslo? No tak ako v desiatkovej – jedna! Pretože jednociferné čísla môžeme napísať aj ako dvoj / troj ... ciferné a to tak, že pridáme najmenšie číslo – nula: 1 = 01 = 001 ... Takže číslo jedenásť v jedenástkovej sústave zapíšeme ako 10, pokračujme vo výpise nasledujúcich čísel v tejto sústave: 11, 12, 13, 14, 15, 16, 17, 18, 19, 1A, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 2A, 30...

            So zvyšovaním „stupňa“ sústavy, zvyšujeme aj písmenka. Teda šestnástková (hexadecimálna) stúpa až do písmena F, teda analogicky ako v predchádzajúcom príklade, do 16-1 (stále uvažujme univerzálne, 10 = sústava jedenástková – 1) čísla, teda 15 je táto sústava jednociferná: 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F a potom postupujeme ďalej: 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 1A, 1B, 1C, 1D, 1E, 1F, 20, 21, 22...

            Takže poďme konvertovať desiatkovú sústavu do hexadecimálnej (napr. decimálne číslo 42.489):

 

            Teraz, keď už máme skúsenosti s konverziou desiatkovej sústavy do ľubovoľnej sústavy, pozrime sa na problematiku úplne univerzálne:

 

            Tak si to teda poďme naprogramovať. Je úplne jedno, aký programovací jazyk zvolíme (Visual Basic, Delphi, C) a tak ja použijem syntax Pascalu, ktorý je začiatočníkom blízky a pritom dobre čitateľný aj „céčkarom“. Najprv načítame vstupné desiatkové číslo a potom sa spýtajme na sústavu.

            Ako sa dá vyčítať z univerzálnej metódy konverzie desiatkového čísla budeme potrebovať jeden cyklus, ktorý sa neskončí dovtedy, kým sa delené číslo nerovná nule. Tu však treba dať pozor na sústavu menšiu ako binárnu, pretože taká sústava nedáva zmysel. Aby sme mohli šikovne spracúvať kroky 1 – 3 (zaokrúhľovanie, opätovné násobenie a odčítanie) použijeme metódu delenia zvyškov. Skúsenejší programátori ju isto poznajú. Ak delíme celé čísla (príkaz dev) hneď sa nám hodnota zaokrúhľuje nadol, jedná sa teda o tzv. celočíselné delenie so zvyškom. Ten zvyšok sa dá získať rovnako ako delenec s tým, že použijeme príkaz mod.

            Potom musíme zabezpečiť pridelenie písmenka. Ak je to nutné, zistíme, že prvé písmenko v abecede má ordinálne číslo 55 (napr. príkazom writeln(ord(‘A’));) a od toho sa budeme odrážať. Príkaz, ktorý vypíše znak z ordinálneho čísla je zase chr (viac v prvom linku na úvode tohto článku). K vypočítanému index písmenka v abecede prirátame 55 (56 v ord. Je B, 57 C a analogicky). Môžeme zvoliť aj inú metódu, napríklad výpis všetkých písmen do konštanty a priamo volať na index toho – ktorého písmenka, je to na každom z nás – veď práve o tom je programovanie J, koľko ľudí, toľko rôznych zdrojových kódov na jediný problém!

            Tak tu je univerzálny program so zdrojovým kódom v Pascale na konverziu desiatkovej sústavy do ľubovoľnej inej sústavy, ako vidno, je ešte jednoduchší ako spôsob, ktorým rátame „ručne“:

 

(* Konvertuje cislo do retazca *)

function IntToStr(I: Longint): String;

var S: string;

begin

Str(I, S); IntToStr := S;

end;

 

Var Vysledok: String;

  Zvysok,Sustava: Byte;

Vstup: Integer;

begin

Vysledok:='0';

Write('Zadaj cislo: '); Readln(Vstup);

Write('Zadaj ciselnu sustavu konverzie: '); Readln(Sustava);

If Sustava > 1 then begin

Vysledok:='';

While Vstup > 0 do begin

Zvysok:=Vstup mod Sustava;

If Zvysok>9 then Insert(Chr(Zvysok+55),Vysledok,1) else Insert(IntToStr(Zvysok),Vysledok,1);

Vstup:=Vstup div Sustava;

end;

end;

Writeln('Vysledne cislo = ',Vysledok);

end.

 

Pozor: Metóda, ktorá tu bola prezentovaná platí len pre kladné čísla a celé. Napr. aj v binárnej sústave môžeme zobraziť desatine čísla, ale s týmto sa začínajúci programátor nestretne...

 

Príloha