# 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

