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

262 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 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 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 10+38
- Přesnost na cca 6 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 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 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 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 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