FAV-ZCU/KIV PPA1/18. Zobrazení dat v počítači.md

262 lines
12 KiB
Markdown
Raw Permalink Normal View History

# 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ř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