IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

3. diel - Reprezentácie čísel v počítači

V minulej lekcii, Prenos bitov aneb od pántov vedú drôty ... , sme sa pozreli na to, ako sa prenáša bity a bajty. Teraz sme v situácii, keď už sme nejako dostali bity odniekiaľ niekam vo forme dátového prúdu. Dokonca sme si aj určili, že dáta nasekáme na bloky. Stále to sú ale len nuly a jednotky. A ak s nimi chceme niečo robiť, musíme sa sa rozhodnúť, ako prevedieme túto sekvenciu na čísla. Ak sa vám až doteraz zdalo, že sa tu bavíme len o teoretických veciach, tak dnes nadobudnú konkrétnu podobu. Ukážeme si, aké sú s číslami a ich prevody problémy :)

Reprezentácie celých čísel

Začneme celými číslami, ktoré sú samozrejme pre ukladanie najjednoduchšie.

Prirodzená reprezentácie čísiel (unsigned)

Majme čísla, ktoré pre jednoduchosť posielame po 1 bajtu = 8 bitov, teda 8 pozícií pre číslicu 0 alebo 1. Hodnota 0000000 = 0, 11111111 = 255. Táto reprezentácia je bez problémov. Vlastne, malý zádrhel tu je. Ako povedať, že chceme číslo -1 ? Nemáme žiadny znak pre -, posielajú sa iba 0 a 1. Preto sa táto reprezentácia nazýva unsigned = bezznaménková. Záporné čísla v praxi ale bohužiaľ často potrebujeme reprezentovať.

Bias (posun)

Tak dobre, chceme aj záporné čísla, tak si môžeme rozsah posunúť. Kladnú časť skrátime na polovicu a tak dokážeme uložiť hodnoty od -128 do 127 namiesto od pôvodných 0255. Určilo sa, že nula bude kladná, takže je pomer +/- zachovaný. Ku skutočnej hodnote sa pred uložením vždy pripočíta 128 a pri načítaní zas odpočíta.

Ukážme si niekoľko príkladov, ako rôzne čísla uložíme:

-128 = 0,
-127 = 1,
... ,
-1 = 127,
0 = 128,
1 = 129,
...,
127 = 255

Pri prepísanie do binárneho zápisu tento posun vyzerá takto:

-128 = 00000000,
-127 = 00000001,
...,
-1 = 01111111,
0 = 10000000,
1 = 10000001,
...,
127 = 11111111

Táto reprezentácia je pomerne využívaná, má ale jeden háčik. Keď sa pozriete, tak 0 nie je uložená ako 00000000. A to je celkom divné, úplne proti prirodzenému vnímania :)

Znamienkový bit

Skúsme záporné číslo reprezentovať ešte inak. Povedzme, že si vyhradíme najvyššie bit na tzv. Sign bit (znamienkový bit). 1 znamená záporné, 0 znamená kladné. Pre reprezentáciu čísla sa teda dostávame už len na 7 číslic a teda na maximálnu hodnotu 127. Máme opäť možnosť reprezentovať -128127. Vlastne nie tak celkom. Náš rozsah je teraz od -127 do 127, ukážeme si prečo:

-127 = 11111111,
...,
-1 = 1000001,
0 = 00000000,
0 = 10000000,
1 = 00000001,
...,
127 = 01111111

Všimli ste si? Prvý mucha tejto reprezentácie je, že máme +0 a -0. To nám ubralo to jedno záporné číslo, ktoré môžeme reprezentovať. Navyše je to neintuitívne. Čas od času nuly porovnávame. +0 ?= -0...? Rovnajú sa, alebo nie? Má to tiež pár ďalších škaredých vlastností. V bitovom zápise je -127 > -126. No, ale nemôžeme chcieť všetko. Ten nápad je ale celkom dobrý, nešlo by aspoň trochu túto reprezentáciu zlepšiť?

Jednotkový doplnok

Jednotkový doplnok sa snaží riešiť problém, že sú "zápornejší" čísla binárne väčšie. Ak teda chceme záporné číslo, použime doplnok (anglicky ones 'complement). Na také číslo prevedieme tzv. Negáciu a všetky bity obrátime:

-127 = 10000000,
-126 =10000001,
...,
-1 = 11111110,
0 = 00000000,
0 = 11111111,
1 = 00000001,
...,
127 = 01111111

Už je to oveľa lepšie, teraz naozaj platí, že -127 < -126. Len sa nám opäť zduplikovala 0. Navyše celkom nepekne. Každopádne už sme vyriešili jeden problém. Nemôžeme vyriešiť ešte jeden? No, keď sa tak hlúpo pýtam ...

Dvojkový doplnok

Trochu zmätené meno, ale jednotkový bol už použitý. Predstavte si, že čísla budeme reprezentovať pomocou jedničkového doplnku ak tomu prirátame jedničku. Kladné čísla zostanú rovnako kladnými a záporné čísla budú mať pripočítanou jedničku.

-128 = 10000000,
-127 = 10000001,
-126 =10000010,
...,
-1 = 11111111,
0 = 00000000,
1 = 00000001,
...,
127 = 01111111

Pre ilustráciu prikladám obrázok:

dvojkový doplnok - Princípy fungovania počítačov

Vuali, 2 nuly zmizli a nakoniec sme mohli reprezentovať aj hodnotu -128. Tu to teoreticky trochu "hapruje", pretože nemôžete reprezentovať 128, aby ste si sami vykonali túto operáciu, ale na iných číslach to funguje. Navyše máme stále sign bit zachovaný.

Využitie jednotlivých reprezentácií v praxi

Kde sa ktorá reprezentácie používa? Sem tam sa používa unsigned, pomerne často Bias a najčastejšie je dvojkový doplnok, zvlášť u desatinných čísel, o tom však až za chvíľu.

Pretečeniu

Len ešte poznámečka, než sa dostaneme k tomu, že "chceme viac". Ponúka sa otázka, čo sa stane, keď k 127 pripočítame 1. No, 0111111 + 00000001 = 10000000 = -127. Také pekné, malé, nenápadné pretečeniu. Dávajte si na to pozor, je to nenápadná chybička a nikto vám nič nepovie. Pre počítač je to úplne validný inštrukcie a je možné, že ste to tak chceli. Kontrolujte si svoje typy, v dnešných pamätiach nehrá úspora takú rolu, aby ste museli šetriť každý kus. Píšte kód zrozumiteľne, prehľadne a bezpečne. (Na druhej strane predsa len nie je úplne rozumné ukladať vek človeka v Long :) )

Reprezentácia čísel v dvojkovej sústave - Princípy fungovania počítačov

Reprezentácie väčších čísel

Čo keď chceme väčšie čísla než 127 ? Mimochodom, tento číselný typ existuje ako byte. Môžeme predsa mať napríklad typ int od -2147483648 do 2147483649. Ďalšie typy sa výrazne líši u každej implementácie jazyka. Java napr. Unsigned nemá, ale v C # je možné mať aj uint (unsigned int) v intervale <0, 4294967295>. Existujú aj short, long, char a ďalšie typy. Tie ale nechajme bokom.

Prevádzanie medzi typmi

Používajme dvojkový doplnok, ktorý je najbežnejšie a možno aj vďaka týmto prevodom sa najlepšie osvedčil. Pre ďalšie prevody budem predpokladať, že zväčšujeme či zmenšujeme rozsah dvakrát. Čisto z praktických dôvodov, stránka má obmedzenú šírku. V zátvorkách sú uvedené príklady takýchto konverzií.

Prevod z menšieho rozsahu čísla na väčšie (int => long)

Ak je číslo kladné alebo záporné, rozkopírujeme signed bit:

1B = 8b 2B = 16b desiatkový zápis
00000001 0000000000000001 1 => 1
10000001 1111111110000001 -127 => -127
Prevod z väčšieho rozsahu čísla na menšie (long => int)

Ak je číslo v rozsahu toho menšieho, či už kladné, alebo záporné, nie je problém. Ak je však číslo vo väčšom rozsahu než menšie z nich, máme problém ...

2B = 16b 1B = 8b desiatkový zápis
1111111110011001 10011001 -147 => -147
0000000000000110 00000110 6 => 6
1110111110011001 10011001 -4199 => -147
0001100000000000 00000000 6144 => 0
Ak si nie ste naozaj istí, čo máte v Long dosadené, pozor na prevody!

Reprezentácie reálnych čísel

Keď sme sa rozohriali, prejdime rovno na reprezentáciu reálnych čísel. Musíme si totiž uvedomiť, čo vlastne chceme. Delili ste niekedy na kalkulačke číslo 10 / 3 * 2 ? Vyšlo vám väčšinou niečo ako 6,66666666667. Matematicky je to nezmysel, lenže počítač v sebe nemá nič nekonečné. Čokoľvek, čo robí, robí s konečnou pamäťou a konečným časom. Proste nemáme niekoľko gigabajtov voľného priestoru len na uloženie (a to ešte nepresného) výsledku. Napriek tomu ale môžeme reprezentovať desetinnáa čísla pomerne slušne. Možno vás napadlo 1100,01 = 12,25. Čiarku ale samozrejme tiež nemáme. Čo s tým?

Pevná desatinná čiarka

Môžeme si určiť, že desatinná čiarka bude tam a tam. Napr., Že 3 cifry budú vždy za desatinnou čiarkou a teda 5 cifier zostane na číslo. Pre jednoduchosť uvažujme unsigned typ (teda nezáporné číslo). Takto by sme zapísali napr. Čísla 00101,001 = 5,25 a 01101,001 = 13,5. (Desatinná čiarka je v binárnom zápise samozrejme len pre nás pre prehľadnosť).

Pre lepšiu zápis môžeme čísla ukladať ako mocniny dvojky (v exponenciálnom tvare, tzv. Mantisa), teda ako 1,101001 * 2^3. Stále sa ale jedná o veľmi podobný zápis ako sú Integer, len mám v nejakom protokole zaznamenané, ako desatinné čísla vyzerajú.

Sčítanie funguje dobre, máme pri sebe blízko podobne veľké čísla a všetko je v poriadku. Čo keď ale chceme počítať s číslami, bez toho aby sme vopred poznali ich rozsah? Ak počítame izbovú teplotu, môžeme si pevnú desatinnú čiarku dovoliť. Čo ale keď budeme chcieť počítať finančné transakcie a zrovna na potvoru sa na bankový aplikáciu prihlási Bill Gates a Jenda Podšívka z Horných šišiek u Dubenic ...

Plávajúce desatinná čiarka

U plávajúce desatinnej čiarky si priamo povieme, koľko bajtov sa používa pre Mantis (číslo bez desatinnej čiarky) a exponent (čím násobíme Mantis). Pre 8 bitov sa používa práve 1 sign bit, 2 bity exponent a 5 bitov mantisa. Zvyšok zahodíme. Z toho vyplýva, že desatinné čísla nie sú moc presná. Prečo sa tomu hovorí plávajúce? Aneb pretože nemáme pevne zadrôtovanou, kde v tom čísle desatinná čiarka bude.

Plávajúce desatinné čísla - Princípy fungovania počítačov

Tu si môžeme všimnúť ešte jednej zvláštnej hodnoty, NaN. V desatinných číslach totiž ide deliť nulou ... Áno, celý vesmír sa rúca, ale nie tak celkom. Proste dostaneme výsledok "Not a number", čo je také príjemné číslo. Nemôžete s ním robiť nič a akákoľvek operácia s ním vám vyhodí znova NaN. Pre ukážku máte ešte jeden obrázok ukazujúci typy desatinných čísel. (Float a double):

Typy desatinných čísel – float a double - Princípy fungovania počítačov

Dokonca si môžeme dovoliť prvú jednotku vôbec nepísať, čím spresníme zápis čísla. Každé číslo sa skladá zo sign bitu, mantisy a exponentu. Mantisa môže byť vo dvojkovom doplnku a v exponentu sa používa Bias (pozri vyššie). Keďže máme Bias, exponent môže byť aj záporný, čo znamená reálne čísla od 0 do 1 či od -1 do 0. Rozdiel jasnejšie opíše tabuľka nižšie:

Princípy fungovania počítačov

Pozn .: Shared exponent tu má zmysel, pretože všetky fixed point čísla majú "rovnako hodnotný" prvý bit.

Pozor!

Keď sa pozriete na tabuľku vyššie, tak plávajúce desatinná čiarka je očividne veľmi nepresná notácie. Veľa bitov zahadzuje. Nikdy, naozaj nikdy preto nepoužívajte na porovnávanie float či double čísel ==. Ak máte číslo a a číslo b, tak robte niečo ako a – b < 0.0001 či niečo podobné. Môže sa stať, že sa čísla jednoducho o kúsok mínou a podmienka neprejde, aj keď by ste očakávali, že áno. Ak môžete, používajte celé čísla. A ak z toho máte v hlave guláš, vedzte, že nebudete prvý, ani posledný. Tak hlavu hore :)

Princípy fungovania počítačov

V budúcej lekcii, Babylonskej zmätenie kódovanie , sa pozrieme pre zmenu na reprezentáciu textu.


 

Predchádzajúci článok
Prenos bitov aneb od pántov vedú drôty ...
Všetky články v sekcii
Princípy fungovania počítačov
Preskočiť článok
(neodporúčame)
Babylonskej zmätenie kódovanie
Článok pre vás napísal Ondřej Michálek
Avatar
Užívateľské hodnotenie:
1 hlasov
Autor se věnuje teoretické informatice. Ve svých volných chvílích nepohrdne šálkem dobrého čaje, kaligrafickým brkem a foukací harmonice.
Aktivity