263 lines
12 KiB
Markdown
263 lines
12 KiB
Markdown
|
# Zobrazení dat v počítači
|
|||
|
|
|||
|
- Všechna data uložená v počítači jsou uložena jako posloupnost binárních číslic (bitů) uspořádaná po bytech (8 bitů)
|
|||
|
- Způsob uložení dat se nazývá **kódování**
|
|||
|
- Je dán datovým typem dat
|
|||
|
- Určuje, jaký mají význam jednotlivé bity a byty
|
|||
|
- Rozsahy hodnot jednotlivých datových typů a počet bytů, které zabírají v paměti, byly zmíněny v Kap. 3.2
|
|||
|
- Jakým způsobem jsou jednotlivé datové typy uloženy (jaké kódování je použito), je popsáno v následujících podkapitolách
|
|||
|
|
|||
|
### Převod čísel mezi soustavami
|
|||
|
|
|||
|
- Nativní číselná soustava počítače, odpovídající uspořádání fyzické paměti, je dvojková (binární)
|
|||
|
- Ruční zápis binárních čísel je však dlouhý, proto se pro zápis binárních čísel často používá šestnáctková (hexadecimální) soustava, která pro stejné číslo potřebuje 4x méně číslic
|
|||
|
- Na jeden byte stačí 2 hexadecimální číslice, ale 8 binárních číslic
|
|||
|
- V běžném životě se většinou počítá v desítkové (dekadické) soustavě
|
|||
|
- Čísla lze mezi jednotlivými soustavami převádět pomocí kalkulačky či jiných programů (přepočet je dostupný např. v PSPadu)
|
|||
|
- Algoritmy pro ruční převod čísel mezi dvojkovou, desítkovou a šestnáctkovou soustavou jsou v následujících podkapitolách
|
|||
|
|
|||
|
#### Převod z desítkové do dvojkové soustavy (univerzální postup)
|
|||
|
|
|||
|
- Celou a desetinnou část řešíme zvlášť
|
|||
|
- Celá část
|
|||
|
- Celou část dělíme 2, píšeme si zbytky po dělení
|
|||
|
- Poslední číslice výsledku (0 nebo 1) a zbytky přečtené odzadu dají celou část binárního čísla
|
|||
|
- Desetinná část
|
|||
|
- Desetinnou část násobíme 2, píšeme si číslici vlevo od desetinné čárky (v celé části)
|
|||
|
- Číslice přečtené popředu dají desetinnou část binárního čísla
|
|||
|
- Příklad převodu čísla 69,6875 na jeho reprezentaci v binární soustavě je na
|
|||
|
|
|||
|
#### Převod z desítkové do dvojkové soustavy („intuitivní“)
|
|||
|
|
|||
|
- „Intuitivní“ postup pro celá čísla
|
|||
|
- Napsat si vyčíslené mocniny 2, nalézt největší menší nebo stejnou mocninu 2, zapsat pod ní 1 a odečíst ji od převáděného čísla
|
|||
|
- Opakovat, dokud z čísla nezbude 0
|
|||
|
- Příklad převodu 69 na jeho reprezentaci v binární soustavě
|
|||
|
- Odečtu 64, protože 64 < 69, pod 64 zapíšu 1, zbude 5
|
|||
|
- Odečtu 4, protože 4 < 5, pod 4 zapíšu 1, zbude 1
|
|||
|
- Odečtu 1, protože 1 = 1, pod 1 zapíšu 1, zbude 0
|
|||
|
- Zbytek pozic doplním 0
|
|||
|
|
|||
|
#### Převod z dvojkové do desítkové soustavy
|
|||
|
|
|||
|
- Převod z dvojkové soustavy do desítkové (pro celá i reálná čísla)
|
|||
|
- Každou číslici označit zprava doleva jako zvyšující se mocninu 2
|
|||
|
- Mocniny u číslic 1 vyčíslit a sečíst
|
|||
|
|
|||
|
#### Převod z dvojkové do šestnáctkové soustavy
|
|||
|
|
|||
|
- Převod z dvojkové soustavy do šestnáctkové (pro celá i reálná čísla)
|
|||
|
- Rozdělit číslo na čtveřice od desetinné čárky (na obě strany)
|
|||
|
- Každá čtveřice je jedna číslice šestnáctkové soustavy (0 až F)
|
|||
|
- Vyčíslit hodnotu čtyř binárních číslic jako při převodu do desítkové soustavy
|
|||
|
|
|||
|
#### Převod z šestnáctkové do dvojkové soustavy
|
|||
|
|
|||
|
- Převod z šestnáctkové do dvojkové soustavy (pro celá i reálná čísla)
|
|||
|
- Každou šestnáctkovou číslici převést do desítkové soustavy
|
|||
|
- Použít pro každou číslici intuitivní postup pro převod z desítkové do dvojkové soustavy
|
|||
|
|
|||
|
### Kódy pro uložení celočíselných datových typů
|
|||
|
|
|||
|
- Pro uložení celočíselných datových typů existuje několik kódů
|
|||
|
- Bezznaménkové
|
|||
|
- Znaménkové
|
|||
|
- Přímý kód
|
|||
|
- Inverzní kód
|
|||
|
- Doplňkový kód
|
|||
|
- Kód s posunutou nulou
|
|||
|
|
|||
|
#### Uložení celých čísel bez znaménka
|
|||
|
|
|||
|
- Zápis ve dvojkové soustavě zarovnaný na násobky bytů
|
|||
|
- Pouze pro nezáporná čísla
|
|||
|
- Např. 131 je ```1000 0011```, 3 je ```0000 0011```
|
|||
|
|
|||
|
#### Přímý kód
|
|||
|
|
|||
|
- Kladná čísla stejná jako u bezznaménkového kódování
|
|||
|
- Znaménko určeno v MSB (Most Significant Bit – ten nejvíce vlevo)
|
|||
|
- Např. -3 je 1000 0011
|
|||
|
- Nevýhody
|
|||
|
- Dvojí nula ```– 1000 0000``` (záporná) a ```0000 0000``` (kladná)
|
|||
|
- Používá se pro zobrazení mantisy u reálných čísel
|
|||
|
|
|||
|
#### Inverzní kód
|
|||
|
|
|||
|
- Kladná čísla stejná jako u bezznaménkového kódování
|
|||
|
- Pro záporná čísla se mění všechny ```0``` na ```1``` a ```1``` na ```0```
|
|||
|
- Např. -3 je ```1111 1100```
|
|||
|
- Nevýhody
|
|||
|
- Dvojí nula ```1111 1111``` (záporná) a ```0000 0000``` (kladná)
|
|||
|
- Používá se v bitových operacích, případně jako mezikrok v doplňkovém kódu
|
|||
|
|
|||
|
#### Doplňkový kód (dvojkový doplněk)
|
|||
|
|
|||
|
- Matematická definice
|
|||
|
- D(x) = x pro x ≥ 0
|
|||
|
- D(x) = x + K pro x < 0, kde K = $2^{n}$ (kapacita soustavy)
|
|||
|
- Kladná čísla stejná jako u bezznaménkového kódování
|
|||
|
- Záporná čísla jsou uložena jako „inverzní kód + 1“
|
|||
|
- Např. -3 je ```1111 1101```
|
|||
|
- Používá se výhradně pro uložení celých znaménkových čísel
|
|||
|
- Např. typy ```byte, short, int, long``` v Javě
|
|||
|
- Výhody
|
|||
|
- Pouze jedna nula – ```0000 0000```
|
|||
|
- Odečítání je přičítání záporného čísla
|
|||
|
- Pozor na nesymetrický rozsah -128 až 127 (pro 1 byte)
|
|||
|
- Absolutní hodnota nejmenšího záporného čísla je mimo rozsah
|
|||
|
- Přetečení
|
|||
|
- Nastává, když nám aritmetickými operacemi vyjde hodnota, která se nevejde do daného rozsahu
|
|||
|
- Např. 127 + 1 (pro 1 byte) = -128
|
|||
|
- MSB se přičtením 1 k maximálnímu číslu nastaví na 1, což indikuje záporné číslo, proto vyjde -128
|
|||
|
- Možné reakce na přetečení
|
|||
|
- Přerušení výpočtu jako reakce na chybu
|
|||
|
- Pokračování výpočtu s nesprávným výsledkem – používá Java
|
|||
|
- Zda přetečení nastane, závisí na vstupních číslech – někdy může program fungovat správně a někdy ne => špatně se hledá
|
|||
|
|
|||
|
#### Kód s posunutou nulou
|
|||
|
|
|||
|
- Lineární posun nuly po celočíselné ose
|
|||
|
- ```0000 0000``` je nejmenší (záporné) číslo
|
|||
|
- Nula je ve středu rozsahu, tedy $2^{n-1}$ – 1, např. ```0111 1111```
|
|||
|
- ```1111 1111``` je největší kladné číslo
|
|||
|
- Podobně jako u doplňkového kódu je rozsah nesymetrický
|
|||
|
- Nevýhoda
|
|||
|
- Kladná čísla jsou odlišná od bezznaménkového kódování
|
|||
|
- Např. 3 je ```1000 0010```
|
|||
|
- Používá se pro uložení exponentu u reálných čísel
|
|||
|
|
|||
|
### Kódy pro uložení reálných datových typů
|
|||
|
|
|||
|
- Aproximace reálných čísel
|
|||
|
- Též nazýváno „zobrazení v pohyblivé řádové čárce“ (floating point)
|
|||
|
- Dle normy IEEE 754 na 4 nebo 8 bytech (v Javě ```float``` – 4 byty a ```double``` – 8 bytů)
|
|||
|
- Kromě samotného kódování norma IEEE 754 definuje i standardní chování základních aritmetických operací (sčítání, odčítání, násobení, dělení, …)
|
|||
|
|
|||
|
#### IEEE 754 na 4 bytech
|
|||
|
|
|||
|
- Formát v pohyblivé řádové čárce s jednoduchou přesností (single-precision floatingpoint format)
|
|||
|
- Používá 4 byty (32 bitů)
|
|||
|
- Rozsah v absolutní hodnotě cca 10-45 až 10+38
|
|||
|
- Přesnost na cca 6 až 7 (dekadických) desetinných míst
|
|||
|
- Rozdělení na znaménko, exponent a mantisu
|
|||
|
- Znaménkový bit patří mantise (nikoliv exponentu)
|
|||
|
- 0 odpovídá +
|
|||
|
- 1 odpovídá -
|
|||
|
- Mantisa (23 bitů)
|
|||
|
- Uložena v přímém kódu (znaménkový bit je oddělen exponentem)
|
|||
|
- Je normovaná
|
|||
|
- 1 ≤ mantisa < základ (tj. 2)
|
|||
|
- Její první bit v normovaném tvaru musí tedy být vždy 1 (1 před desetinou čárkou) a proto se neukládá
|
|||
|
- Určuje přesnost čísla
|
|||
|
- Exponent (8 bitů)
|
|||
|
- Uložen v kódu s posunutou nulou, kde 0 je ```0111 1111```
|
|||
|
- Určuje rozsah čísla
|
|||
|
- Hodnota 0 je uložena jako samé nuly
|
|||
|
- Hodnota čísla se dá vypočítat
|
|||
|
- Určení, jak bude vypadat zápis v IEEE 754 na 4 bytech pro číslo -258,125
|
|||
|
- Přesnost uložených čísel je omezená
|
|||
|
- Některá čísla jsou zaokrouhlená
|
|||
|
- Pokud je hodnota čísla menší než minimum, číslo nelze zobrazit, zaokrouhluje se automaticky na 0 => podtečení
|
|||
|
- Pokud je hodnota čísla v absolutní hodnotě větší než maximum, číslo nelze zobrazit, zaokrouhluje se automaticky na (kladné nebo záporné) nekonečno => přetečení
|
|||
|
- NaN (Not a Number)
|
|||
|
- Definovaná hodnota při chybné operaci s reálným číslem (např. dělení nuly nulou)
|
|||
|
- Operace s reálnými čísly
|
|||
|
- Sčítání
|
|||
|
- Porovnáním exponentů se zjistí menší číslo, tomu se zvětší exponent na úroveň většího čísla => zmenšuje se přesnost (mantisa)
|
|||
|
- Pro exponentem hodně odlišná čísla se může v důsledku místo menšího čísla přičítat nula
|
|||
|
- Násobení
|
|||
|
- Exponenty se sečtou
|
|||
|
- Mantisy se vynásobí
|
|||
|
- Obecně platí
|
|||
|
- Nepoužívat reálná čísla tam, kde stačí celá
|
|||
|
- Výpočty nemusí být přesné (zaokrouhlovací chyby)
|
|||
|
- Výpočty s celými čísly mohou být rychlejší
|
|||
|
- Nepoužívat pro reálná čísla porovnání na rovnost (operátor „```==```“)
|
|||
|
|
|||
|
#### IEEE 754 na 8 bytech
|
|||
|
|
|||
|
- Formát v pohyblivé řádové čárce s dvojitou přesností (double-precision floating-point format)
|
|||
|
- Používá 8 bytů (64 bitů)
|
|||
|
- Přesnost na cca 15 (dekadických) desetinných míst
|
|||
|
- Způsob uložení je úplně stejný jako u 4 bytů, jen se liší velikost exponentu a mantisy
|
|||
|
- Znaménko 1 bit
|
|||
|
- Mantisa 52 bitů
|
|||
|
- Exponent 11 bitů
|
|||
|
|
|||
|
### Kódy pro uložení znaků a řetězců
|
|||
|
|
|||
|
#### Uložení znaků
|
|||
|
|
|||
|
- Přiřazují každému znaku zvolené abecedy nezáporné celé číslo
|
|||
|
- Existuje mnoho kódů
|
|||
|
|
|||
|
#### Uložení řetězců
|
|||
|
|
|||
|
- Řetězec je složen z jednotlivých znaků (v daném kódování)
|
|||
|
- Řetězec má délku udávanou v počtu znaků
|
|||
|
- Způsob uložení v paměti závisí především na použitém programovacím jazyce
|
|||
|
- Java
|
|||
|
- String
|
|||
|
- Řetězec je neměnná (immutable) instance třídy
|
|||
|
- Znaky řetězce jsou v instanci uloženy jako pole znaků (char[])
|
|||
|
- Řetězec tak může mít libovolnou délku
|
|||
|
- ```StringBuilder/StringBuffer```
|
|||
|
- Měnitelný řetězec
|
|||
|
- Kromě délky má i kapacitu (kolik znaků lze do řetězce uložit), která je rovněž proměnná
|
|||
|
- Znaky řetězce jsou v instanci rovněž uloženy jako pole znaků (char[])
|
|||
|
- Řetězec tak může mít libovolnou délku
|
|||
|
- C
|
|||
|
- Řetězec je pole bytů začínající indexem 0
|
|||
|
- Za posledním platným znakem řetězce je přidán znak s hodnotou 0 (tj. '\0' – nikoliv znak '0')
|
|||
|
- Řetězec tak může mít libovolnou délku
|
|||
|
- V řetězci se nesmí vyskytnout znak '\0'
|
|||
|
- Pascal
|
|||
|
- Řetězec je pole bytů, znaky jsou uloženy od indexu 1
|
|||
|
- Na indexu 0 je uložena délka řetězce, která je tak omezena na maximálně 255 znaků
|
|||
|
- Platí pro původní specifikaci jazyka Pascal
|
|||
|
- Jeho novější mutace (např. FreePascal) obsahují i další typy řetězců
|
|||
|
|
|||
|
### Uložení logického datového typu (```boolean```)
|
|||
|
|
|||
|
- Též booleovský datový typ
|
|||
|
- Ukládají se jen dvě hodnoty
|
|||
|
- ```true``` (pravda, logická 1)
|
|||
|
- ```false``` (nepravda, logická 0)
|
|||
|
- Prakticky se realizují pomocí celočíselného bezznaménkového typu
|
|||
|
- Některé jazyky specifický logický typ nemají a používají místo něj celočíselný typ
|
|||
|
- Např. C
|
|||
|
|
|||
|
### Problém ukládání dat do fyzické paměti
|
|||
|
|
|||
|
- Týká se všech datových typů, jejichž hodnoty jsou uloženy na více než jednom bytu tj. většina)
|
|||
|
- Demonstrujeme na uložení neznaménkového čísla na 4 bytech (01A2B3C4)H počínaje adresou 1000
|
|||
|
- Pokud má datový typ větší délku než jeden byte, pak jsou dvě možnosti, jak tyto byty uložit do fyzické paměti
|
|||
|
- Big Endian (BE) – „vyšší řády na nižší adrese“ – „přirozené“ uložení
|
|||
|
- Číslo bude uloženo jako ```01 A2 B3 C4```
|
|||
|
- Adresa 1000: ```01```
|
|||
|
- Adresa 1001: ```A2```
|
|||
|
- Adresa 1002: ```B3```
|
|||
|
- Adresa 1003: ```C4```
|
|||
|
- Little Endian (LE) – „vyšší řády na vyšší adrese“ – „obrácené“ uložení
|
|||
|
- Číslo bude uloženo jako ```C4 B3 A2 01```
|
|||
|
- Adresa 1000: ```C4```
|
|||
|
- Adresa 1001: ```B3```
|
|||
|
- Adresa 1002: ```A2```
|
|||
|
- Adresa 1003: ```01```
|
|||
|
- Obecně se nedá říct, s kterým způsobem se setkáme více
|
|||
|
- Je běžné, že se oba způsoby vyskytují na jednom počítači
|
|||
|
- Může způsobit potíže při zápisu a následném čtení binárních souborů
|
|||
|
- Je potřeba vědět, zda je soubor zapsán jako LE nebo BE
|
|||
|
- Způsob záleží na
|
|||
|
- Procesoru
|
|||
|
- Např. Intel LE, Motorola BE
|
|||
|
- Operačním systému
|
|||
|
- Windows LE
|
|||
|
- Programovacím jazyce
|
|||
|
- Java BE
|
|||
|
- Zaručuje přenositelnost binárních souborů
|
|||
|
- Pokud však byly zapsány i přečteny programem napsaným v Javě
|
|||
|
- V mnoha programovacích jazycích není určen a přebírá se způsob od operačního systému
|
|||
|
|