Úvod do programování 7. hodina RNDr. Jan Lánský, Ph.D. Katedra informatiky a matematiky Fakulta ekonomických studií Vysoká škola finanční a správní 2015
Umíme z minulé hodiny Syntax Znaky Vlastní implementace řetězcových algoritmů jsou výborné na procvičení schopností práce s polem Textové řetězce Algoritmy Lexikografické uspořádání Zřetězení, podřetězec Hledání indexu výskytu znaku, řetězce Vymazání, vložení a nahrazení znaku, řetězce Změna hodnoty znaku na pozici dané indexem Naše vlastní řetězce Jan Lánský Úvod do programování 7. hodina 2
Cíle hodiny Algoritmy Hornerovo schéma Převod mezi číselnými soustavami Dlouhá celá čísla (reprezentace) Součet, rozdíl, součin, podíl Dlouhá reálná čísla (reprezentace) Zlomky (reprezentace) Syntax Konstanty Jan Lánský Úvod do programování 7. hodina 3
Hornerovo schéma - Motivace Vyhodnocení polynomu pro zadané x 2x 4 +7x 3 5x 2 6x + 7 2*x*x*x*x + 7*x*x*x 5*x*x 6*x + 7 10 násobení, obecně n 2 ((( 2*x+7)*x 5)*x 6)*x+7 4 násobení, obecně n Využití: převod čísla z jedné číselné soustavy do druhé Jan Lánský Úvod do programování 7. hodina 4
Hornerovo schéma - Formálně Polynom: a 0 + a 1 x + + a n x n vyhodnotíme pro zadané x 0 b n = a n b n-1 = b n *x 0 +a n-1 Výsledek b 0 Převod čísla N p (= koeficienty polynomu a i ) zapsaného v číselné soustavě o základu p (=x 0 ) na číslo N q (=b 0 ) zapsané v číselné soustavě o základu q (v této soustavě vyhodnocujeme aritmetické operace) Koeficienty polynomu = číslice V praxi se nejčastěji používá pro převod čísel zapsaných v soustavách o základech 2, 8, 16 na čísla zapsaná v soustavách o základu 10 Jan Lánský Úvod do programování 7. hodina 5
Příklady: převody čísel do desítkové soustavy 1011001 2 = 89 10 (((((1*2+0)*2+1)*2+1)*2+0)*2+0)*2+1 41672 8 = 17338 10 (((4*8+1)*8+6)*8+7)*8+2 B1D6 16 = 45526 10 ((11*16+1)*16+13)*16+6 Jan Lánský Úvod do programování 7. hodina 6
Převod řetězce na číslo Aplikace Hornerova schématu: v řetězci jsou přirozeným způsobem uloženy jednotlivé cifry (= koeficienty polynomu) Převod znaku na číslici. Číslice jsou uspořádány za sebou Obdoba funkce Convert.ToInt32 Jan Lánský Úvod do programování 7. hodina 7
Převod mezi číselnými soustavami Obecně lze Hornerovo schéma použít na převod mezi libovolnými dvěmi číselnými soustavami, např. 8 11 V praxi se používá na převod z jiné číselné soustavy do desítkové, např. 2 10 Z desítkové do jiné číselné soustavy se používá reverzní postup: Metoda dělení základem. Převod z obecné číselné soustavy do jiné se provádí s mezikrokem desítkovou soustavou (např. 8 10 11) V desítkové soustavě se nám dobře provádí aritmetické operace Jan Lánský Úvod do programování 7. hodina 8
Metoda dělení základem Reverzní k Hornerově schématu Převod čísla N 10 v desítkové soustavě na číslo N q v soustavě q Operace v desítkové soustavě jdou snadno Postupně číslo N 10 celočíselně dělíme q a zapisujeme zbytky po celočíselném dělení. První zbytek je nejméně významná číslice, poslední zbytek je nejvýznamnější číslice. Jan Lánský Úvod do programování 7. hodina 9
Příklady: převody čísel z desítkové soustavy 13 10 = 1101 2 13 = 6 * 2 + 1 6 = 3 * 2 + 0 3 = 1 * 2 + 1 172603 10 = 2A23B 16 172603 = 10787 * 16 + 11 10787 = 674 *16 + 3 674 = 42 * 16 + 2 42 = 2 * 16 + 10 Jan Lánský Úvod do programování 7. hodina 10
Převod z desítkové soustavy do šestnáctkové I. Dokud má 16-kový zápis alespoň dvě cifry Pomocné pole na jednotlivé cifry. Pro jistotu je zbytečné dlouhé, reálně by stačilo 20 Dělíme základem soustavy Je nutné převést na 0 9A F Aktuální cifra, zbytek po dělení Poslední cifra, co zbylo z původního čísla Jan Lánský Úvod do programování 7. hodina 11
Převod z desítkové soustavy do šestnáctkové II. Pole nutno obrátit. Cifry jsme zapisovali od nejméně významné, potřebujeme je mít od nejvíce významné Jen do půlky pole Vytvoříme řetězec z prvků pole od 0 do počtu cifer. Měníme prvek od začátku pole se stejně umístěným prvkem od konce pole 0 až 9 cifry A až F písmena Využíváme uspořádání za sebou Jan Lánský Úvod do programování 7. hodina 12
Dlouhá celá čísla - Motivace Vestavěné datové typy umějí počítat s maximální přesností 30 míst (decimal) Kombinatorika: 49! = 6.08e62 Nezachytíme přesně všechny cifry Jiná než dekadická čísla (šestnáctková) Řešení Vlastní datový typ pro práci s dlouhými čísly Operace + - * / Jan Lánský Úvod do programování 7. hodina 13
Dlouhá čísla reprezentace Pole cifer datového typu int (případně byte, char, int) 1 prvek pole = 1 cifra nebo více cifer První prvek pole Nejvíce významná cifra Nejméně významná cifra Délka pole Přesně podle počtu cifer Větší, dané konstantou Použijeme int - je to plýtvání pamětí, ale nejsou třeba přetypování při implementaci Big Endian Nejsnazší 1 cifra Little Endian Musíme spočítat počet cifer výsledku operace, zbytečně moc náročné Spousta nul navíc, hrozí přetečení. Ale nejsnazší implementace. Lze si pamatovat počet cifer, aby se pro nuly neprováděly operace Jan Lánský Úvod do programování 7. hodina 14
Číslo 17201 reprezentováno na 10 cifer Dlouhá čísla reprezentace Big endian nejvíce významný bit na začátku pole Budeme používat na cvičení 0 0 0 0 0 1 7 2 0 1 Little endian nejméně významný bit na začátku pole Čteme odzadu Budeme používat na přednášce 1 0 2 7 1 0 0 0 0 0 Jan Lánský Úvod do programování 7. hodina 15
Konstanta Proměnná, která je při deklaraci inicializována hodnotou, která se nemůže změnit. Obvykle má smysl být globální Př.: délka pole pro práci s celými čísly Globální konstanty nemají static Globální konstanta maxdel Jan Lánský Úvod do programování 7. hodina 16
Dlouhá čísla - Operace Vytvoření (z řetězce) a výpis (obrazovka) Porovnání Compare 0, -1, 1 Sčítání Odečítání - menšího čísla od většího Násobení Celočíselné dělení: vyžaduje Odečítání, Porovnání a PravýPosun PravýPosun: vynásobení mocninou desítky Implementace: podobná jako školní algoritmus "ruční počítání pod sebe" Jan Lánský Úvod do programování 7. hodina 17
Dlouhá čísla: Vytvoření a výpis Little endian Načítáme cifry odzadu Little endian Vypisujeme cifry odzadu Úvodní nuly skončily Přeskočíme úvodní nuly Jan Lánský Úvod do programování 7. hodina 18
Dlouhá čísla - součet Od nejméně významné cifry po nejvíce významnou cifru Sečteme cifry a přenos z nižšího řádu prenos nabývá hodnot 0 a 1 Z hodnot 0 až 19 uděláme 0 až 9 Jan Lánský Úvod do programování 7. hodina 19
Dlouhá čísla - součet 6 + 2 + 0 = 8 5 + 9 + 0 = 14 0 + 5 + 1 = 6 7 + 0 + 0 = 7 6 + 7 + 0 = 13 8 4 6 7 3 0 0 0 1 0 2 9 5 0 7 4 0 0 0 0 6 5 0 7 6 5 9 9 0 0 0 1 2 3 4 5 6 7 8 9 y = 470592 x = 99567056 i 5 + 4 + 0 = 10 9 + 0 + 1 = 10 9 + 0 + 1 = 10 0 + 0 +1 = 1 0 + 0 + 0 = 0 x+ y = 100037648 Červená došlo k přenosu Zelená bez přenosu Oranžová úvodní nuly Jan Lánský Úvod do programování 7. hodina 20
Dlouhá čísla - rozdíl Musí platit x>=y Od nejméně významné cifry po nejvíce významnou cifru Odečteme cifry a započteme případný přenos z nižšího řádu (0, -1) Podtečení: přenos do vyššího řádu a normalizace hodnoty -10 až 9 na 0 až 9 Jan Lánský Úvod do programování 7. hodina 21
Dlouhá čísla - rozdíl 6-2 + 0 = 4 5-9 + 0 = - 4 0-5 - 1 = - 6 7-0 - 1 = 6 6-7 + 0 = -1 4 6 4 6 9 0 9 9 0 0 2 9 5 0 7 4 0 0 0 0 6 5 0 7 6 5 9 9 0 0 0 1 2 3 4 5 6 7 8 9 5-4 - 1 = 0 9-0 + 0 = 9 9-0 + 0 = 9 0-0 +0 = 0 0-0 + 0 = 0 x - y = 99096464 y = 470592 x = 99567056 i Červená došlo k přenosu Zelená bez přenosu Oranžová úvodní nuly Jan Lánský Úvod do programování 7. hodina 22
Školní algoritmus násobí cifrou celé číslo a tyto součiny sčítá. Náš postup je ekvivalentní Dlouhá čísla - součin Vynásobíme každou cifru x s každou cifrou y Pokud není podmínka splněna, jedná se o cifry oblasti přetečení. Neřešíme Jednotlivé součiny sečteme Normalizujeme cifry výsledku do 0 až 10 pomocí přenosu do vyššího řádu. Vzhledem k volbě datového typu int, funkční i pro čísla o 20 mil. cifrách Jan Lánský Úvod do programování 7. hodina 23
Dlouhá čísla - součin Oranžová úvodní nuly zelená bez přenosu červená - přenos 4 7 7 9 0 14 46 33 6 0 0 4 12 6 0 14 42 21 0 0 2 6 3 0 0 7 2 0 0 0 0 1 2 3 4 vys[i] vys[i+j] j = 1 j = 0 y = 27 x = 362 i 2 * 2 = 4 2 * 6 = 12 2 * 3 = 6 7 * 2 = 14 7 * 6 = 42 7 * 3 = 21 362 * 27 = 9774 14+0 = 4 + 1*10 42+4+ 1= 7 + 4*10 21+12+4=7+3*10 0+6+3=9+0*10 0+0+0 = 0+0*10 Jan Lánský Úvod do programování 7. hodina 24
Dlouhá čísla: pravý posun a porovnání Potřeba pro děleni Posuneme doprava cifry na významnější řády. Pro little endiany je to ekvivalent vynásobení mocninou desítky Prvky nejvíce napravo se zahodí. Předpokládáme, že mají hodnotu nula Analogicky jako lexikografické uspořádání 0 rovnost, -1 první je menší, +1 první je větší Jan Lánský Úvod do programování 7. hodina 25
Dlouhá čísla pravý posun Posun o 2 0 0 6 5 0 7 6 0 0 0 6 5 0 7 6 0 0 0 0 0 0 1 2 3 4 5 6 7 8 9 vys = 6705600 x = 67056 i Červená vložené nuly Zelená - posun Oranžová úvodní nuly Jan Lánský Úvod do programování 7. hodina 26
Dlouhá čísla podíl I. Výpočet posunu Procházíme úvodní nuly na nejvyšších pozicích y, končíme když narazíme na první nenulový prvek. Potřebujeme spočítat kolik řádů rozdílu je mezi x a y. Sledujeme o kolik má y více úvodních nul na nejvyšších pozicích než x. Sledujeme, zda x má příslušných nejvyšších pozicích také úvodní nuly. Pokud x už úvodní nuly nemá, zvyšuje posun. Jan Lánský Úvod do programování 7. hodina 27
Dlouhá čísla podíl I. Výpočet posunu 5-4 - 1 = 0 9-0 + 0 = 9 9-0 + 0 = 9 0-0 +0 = 0 0-0 + 0 = 0 x 2 1 0 0 2 9 5 0 7 4 0 0 0 0 6 5 0 7 6 5 9 9 0 0 0 1 2 3 4 5 6 7 8 9 posun y = 470592 x = 99567056 i Červená došlo ke zvýšení Zelená konec cyklu Žlutá nedošlo ke zvýšení Oranžová úvodní nuly Jan Lánský Úvod do programování 7. hodina 28
Dlouhá čísla podíl II. Iterativní odečítání Dokud y nemá více cifer než x. Posuneme y o daný počet míst doprava (Vynásobíme y mocninou desítky) Za každé odečtení zvýšíme hodnotu cifry na příslušném řádu výsledku. Čím byl nutný vyšší posun, tím vyšší řád Dokud je x větší než posunuté y, od x odečítáme posunuté y V další iteraci budeme y posouvat o jedno místo méně. Jan Lánský Úvod do programování 7. hodina 29
Dlouhá čísla podíl I. Iterativní odečítání Výsledek: vys[2] = 2 Vnitřní cyklus končí, od x už nejde y odečíst. Dojde ke snížení posunu (z 2 na 1) a proběhne další iterace vnějšího cyklu 6 5 6 8 4 4 5 0 0 0 6 5 8 7 0 5 2 5 0 0 0 0 2 9 5 0 7 4 0 0 6 5 0 7 6 5 9 9 0 0 0 1 2 3 4 5 6 7 8 9 2. krok 5448656 1. krok 52508756 y = 47059200 x = 99567056 i Žlutá nová hodnota x Zelená nuly z posunu Oranžová úvodní nuly Jan Lánský Úvod do programování 7. hodina 30
Dlouhá čísla - ukázka Cca 40 cifer, nešlo by přesně v žádném vestavěném datovém typu Pro testování správnosti funkcí webová aplikace Wolfram alfa Jan Lánský Úvod do programování 7. hodina 31
Reprezentace dlouhých reálných čísel Struktura Znaménko, pole cifer, a exponent Přetečení nejvyššího řádu zvýšení exponentu a posun cifer doleva Doposud jsme ignorovali Podtečení nejvyššího řádu snížení exponentu a posun cifer doprava Doposud nemohlo nastat Postupy pro operace podobné jako u celých čísel Implementace na cvičení Jan Lánský Úvod do programování 7. hodina 32
Dlouhá reálná čísla ukázka reprezentace 0 0 0 0 5 0 6 5 8 7-52 + 0 0 0 0 0 0 2 6 5 2 7 + 8 9 6 5 0 9 6 5 0 2 4-0 0 0 6 9 0 0 9 6 5-3 - 0 0 0 0 0 0 0 0 0 9 0 + 785605e-55 256.2e5-20569.05698-0.005690096 9.000000000 Cifry little endian Exponent znaménko Jan Lánský Úvod do programování 7. hodina 33
Reprezentace (dlouhých) zlomků Umožňuje udržovat racionální čísla v nezaokrouhleném stavu. Struktura Znaménko, čitatel a jmenovatel reprezentované pomocí (dlouhého) celého čísla Operace + - * / Postupy jako při ručním počítání Na konci jednotlivých operacích pomocí Euklidova algoritmu převést zlomek na základní tvar. Implementace na cvičení Jan Lánský Úvod do programování 7. hodina 34
Zpětná vazba Objevili jste ve slajdech chyby? Včetně pravopisných Nechápete nějaký slajd? Je příliš obtížný, nesrozumitelný? Máte nějaký nápad na vylepšení? Anonymní formulář Odeslání za pár vteřin http://goo.gl/forms/wxkzqbszls Jan Lánský Úvod do programování 7. hodina 35