Pseudonáhodná čísla = algoritmicky generovaná náhrada za náhodná čísla Použití: - náhodnost při rozhodování např. ve hrách (výběr z více možných stejně dobrých tahů v dané pozici, házecí kostka) - generování rozsáhlých testovacích dat - výpočetní metody typu Monte Carlo Generátor pseudonáhodných čísel - algoritmus, který na základě předchozí hodnoty určí další náhodné číslo v posloupnosti - existuje teorie, jak je vytvářet, my využijeme standardní generátor - při volání generátoru lze zvolit, zda chceme číslo celé či reálné a z jakého rozmezí hodnot Pavel Töpfer, 2017 Programování 1-12 1
Generátor pseudonáhodných čísel v TP RandSeed standardní proměnná typu longint = semínko generátoru, výchozí hodnota pro algoritmus Random funkce volání generátoru - spočítá výslednou hodnotu na základě RandSeed, zároveň nadefinuje novu hodnotu RandSeed pro další volání. Dvě možnosti volání: - volání bez parametru hodnota typu real z intervalu <0,1) - volání Random(N) hodnota typu word z intervalu <0,N-1> Randomize procedura pro inicializaci RandSeed na základě aktuální hodnoty systémového času Pavel Töpfer, 2017 Programování 1-12 2
Inicializace generátoru - provádí se jen jednou na začátku programu. Dvě možnosti: 1. Randomize; při každém běhu programu jiná série náhodných čísel (většinou požadovaný cílový stav) 2. RandSeed := VýchozíHodnota; pokaždé stejná série náhodných čísel použití: dočasně při ladění programu, trvale při šifrování dat apod. Pseudonáhodná čísla z jiného rozmezí - vynásobením změnit rozsah u typu real, přičtením posunout rozsah Příklady: Random(6) + 1 běžná házecí kostka Random * 20-10 reálná čísla z rozmezí od -10 do 10 Pavel Töpfer, 2017 Programování 1-12 3
Příkaz CASE - výběr z více variant podle hodnoty výrazu case Výraz of Hodnota1: Příkaz1; Hodnota2: Příkaz2; HodnotaN: PříkazN end Výraz uvedený za case může být libovolného celočíselného typu, hodnoty musí být konstanty téhož typu. Sémantika: if Výraz = Hodnota1 then Příkaz1 else if Výraz = Hodnota2 then Příkaz2 else if Výraz = HodnotaN then PříkazN Pokud se tedy Výraz nerovná žádné z uvedených hodnot, nevykoná se žádný z příkazů. Pavel Töpfer, 2017 Programování 1-12 4
Rozšíření příkazu case Možnost doplnit implicitní variantu pokud se Výraz nerovná žádné z uvedených hodnot, vykoná se Příkaz z větve else. case Výraz of Hodnota1: Příkaz1; Hodnota2: Příkaz2; HodnotaN: PříkazN; else Příkaz end Přípustné tvary hodnot uváděných u variant: - konstanta 20: - několik konstant oddělených čárkami 20, 22, 24: - interval hodnot 30..40: - kombinace výše uvedených možností 1, 3..7, 9..15, 40: Hodnoty u variant nemusí být navzájem disjunktní vykoná se příkaz z první větve, u které dojde ke shodě hodnoty s výrazem. Pavel Töpfer, 2017 Programování 1-12 5
Příklad: case N of {N je proměnná typu integer} 1: writeln(n); {jedna akce} 2: begin inc(a); dec(b) {více akcí složený příkaz} 0..9: {jiné jednociferné číslo nedělej nic} else writeln( CHYBA ) {víceciferné číslo je chyba} end. Příklad praktického použití: Program potřebuje reagovat podle toho, jaká klávesa byla stisknuta na klávesnici rozhoduje se podle hodnoty proměnné obsahující hodnotu stisknuté klávesy (každá klávesa má nějaký celočíselný kód), je mnoho možností, pro některé klávesy bude stejná reakce. case StisknutaKlavesa of SipkaNahoru: SipkaDolu: SipkaVlevo, SipkaVpravo: Cifra0..Cifra9: else end akce pro šipku nahoru; akce pro šipku dolů; akce pro jinou šipku akce pro dekadickou číslici; akce pro všechny ostatní klávesy Pavel Töpfer, 2017 Programování 1-12 6
Příkaz skoku = předání řízení na určité místo v programu Syntaxe: goto Návěští - Návěští = celé číslo bez znaménka, v TP může být i identifikátor - Návěští se musí deklarovat label Návěští; - cíl skoku (příkaz) v programu se označí Návěští: Ve strukturovaném programování se užívají strukturované příkazy a příkaz skoku prakticky nepotřebujeme. Může být zdrojem mnoha nebezpečí (např. skok dovnitř cyklu) používat skok jen v mimořádných případech! Rozumné strukturované skoky pomocí standardních procedur: continue - předčasné ukončení aktuální iterace cyklu break - předčasné ukončení cyklu exit - předčasné ukončení procedury nebo funkce (příp. programu) halt - předčasné ukončení programu Pavel Töpfer, 2017 Programování 1-12 7
Použití příkazu goto výskok z více vnořených cyklů (break ukončuje pouze jeden cyklus) Příklad: vyhledávání dané hodnoty X v matici čísel A label Konec; const N = 10; M = 15; var X: integer; {hledaná hodnota} A: array[1..n, 1..M] of integer; I, J: integer; for I:=1 to N do for J:=1 to M do if A[I,J] = X then begin {zpracování výsledku} goto Konec Konec: {pokračování výpočtu} Pavel Töpfer, 2017 Programování 1-12 8
Jiné řešení téhož úkolu bez použití příkazu goto, pomocí break: const N = 10; M = 15; var X: integer; {hledaná hodnota} A: array[1..n, 1..M] of integer; I, J: integer; Konec: boolean; Konec := false; for I:=1 to N do begin for J:=1 to M do if A[I,J] = X then begin {zpracování výsledku} Konec := true; break if Konec then break {pokračování výpočtu} Pavel Töpfer, 2017 Programování 1-12 9
Záznam - strukturovaný datový typ - co patří logicky k sobě, ať je u sebe i deklarováno - jednotlivé položky záznamu mohou být různých typů (libovolných, třeba i strukturovaných) - nedají se indexovat jako v poli, mají svá vlastní jména (identifikátory) - jména jednoznačná v rámci záznamu, ale ne vůči okolnímu světu type JménoTypu = record Položka1: TypPoložky1; Položka2: TypPoložky2; PoložkaN: TypPoložkyN - popis položek se řídí stejnými syntaktickými pravidly jako deklarace proměnných Pavel Töpfer, 2017 Programování 1-12 10
type Datum = record Den, Mesic, Rok: word var Dnes, Zitra: Datum; type Zamestnanec = record Jmeno: string[20]; Plat: word; Narozen: Datum; Deti: array[1..10] of string[20]; var Alois: Zamestnanec; Z: array[1..1000] of Zamestnanec; Pavel Töpfer, 2017 Programování 1-12 11
Operace S proměnnou typu záznam lze jako s celkem provádět jedinou operaci, a to dosazení mezi dvěma proměnnými téhož typu: Dnes:=Zitra; Z[3]:=Alois; Přístup ke složkám pomocí tečkové notace: JménoZáznamu.JménoPoložky - se složkou záznamu se pak manipuluje stejně jako s každou jinou proměnnou příslušného typu. Dnes.Den:=31; Dnes.Mesic:=12; read(alois.jmeno); Suma:=Suma + Alois.Plat * 2; Z[3].Narozen.Rok:=1945; Z[3].Deti[1]:= Pepicek ; Pavel Töpfer, 2017 Programování 1-12 12
Příklad: reprezentace polynomu a n x n + a n-1 x n-1 + a n-2 x n-2 + a 1 x + a 0 Dvě varianty: 1. ukládáme všechny členy polynomu včetně nulových, exponent slouží jako index v poli ( snadná manipulace) 2. ukládáme pouze nenulové členy, exponent se ukládá do pole společně s koeficientem (vhodné pro řídké polynomy) type Polynom1 = record Stupen: word; {stupeň polynomu} Koeficient: array[0..maxstupen] of real type Polynom2 = record Pocet: word; {počet nenulových členů} Clen: array[0..maxpocet] of record Koef: real; Exp: word Pavel Töpfer, 2017 Programování 1-12 13
Inicializovaná proměnná typu záznam const LetosniPrvniMaj: Datum = (Den: 1; Mesic: 5; Rok: 2004); type Complex = record X, Y: real const Z: Complex = (X: 2.0; Y: 3.5); Pavel Töpfer, 2017 Programování 1-12 14
Příkaz WITH - použití: pro snadnější přístup k více položkám téhož záznamu - syntaxe: with JménoZáznamu do Příkaz - sémantika: v rámci Příkazu se před každý identifikátor, kde to má syntaktický smysl, jakoby přidá tečkou oddělené JménoZáznamu with Z[1] do read(jmeno, Plat, Narozen.Den, Narozen.Mesic, Narozen.Rok); with Alois do begin Jmeno:= Alois Jirasek ; Plat:= 10000; Deti[1]:= Kaspar ; Deti[2]:= Melichar ; Deti[3]:= Baltazar Pavel Töpfer, 2017 Programování 1-12 15
Výčtový typ type JménoTypu = (Hodnota1, Hodnota2,, HodnotaN); type Dny=(Pondeli, Utery, Streda, Ctvrtek, Patek, Sobota, Nedele); var Den: Dny; - hodnoty: syntakticky identifikátory (pozor na jednoznačnost identifikátorů v rámci celé oblasti deklarací) - interně je reprezentován jako celočíselný typ s hodnotami 0, 1, 2, - pouze dosazení + operace společné pro ordinální typy - použití: v programu k přehlednější evidenci stavu výpočtu, varianty výpočtu apod. (když nestačí dvouhodnotový boolean) Pavel Töpfer, 2017 Programování 1-12 16
Ordinální typy = typy, jejichž hodnoty lze seřadit a očíslovat celými čísly (tzn. přiřadit jim ordinální hodnoty): - celočíselné typy (číslování = identita) - char (ordinální hodnotou je ASCII=kód) - boolean (false=0, true=1) - výčtové typy (číslování = pořadí hodnot v deklaraci typu, od 0) Společné vlastnosti: - funkce ord(x) vrací ordinální hodnotu argumentu - uspořádání hodnot určeno uspořádáním ordinálních hodnot lze porovnávat hodnoty relačními operátory if Den <= Patek then - funkce succ(x) vrací následující hodnotu za X pred (X) vrací předchozí hodnotu před X Den := succ(den); {zítra} Pavel Töpfer, 2017 Programování 1-12 17
-lze vytvářet odvozené typy interval hodnot (typ podobor ) type TypIntervalu = DolníMez.. HorníMez; type Index = 1..50; var I: Index; var Cifra: 0.. 9 ; PracDen: Pondeli..Patek; - lze použít pro indexování polí type JménoTypu = array [OrdTyp] of TypPrvků; type Morse = array[ A.. Z ] of string[4]; var M: Morse; var Permutace: array[index] of Index; Pavel Töpfer, 2017 Programování 1-12 18
-lze použít pro řízení for-cyklu Příklad: četnost znaků v textu var Cetnost: array[char] of word; Z: char; for Z := #0 to #255 do Cetnost[Z] := 0; while not Konec do begin read(z); inc(cetnost[z]) for Z := #32 to #255 do writeln(z, Cetnost[Z]:6); Pavel Töpfer, 2017 Programování 1-12 19
- lze použít v příkazu case Typický příklad: zpracování znaku ze vstupu var Z: char; read(z); case Z of A, a : {akce ANO } N, n : {akce NE } #27: {akce Escape} else {něco jiného} Pavel Töpfer, 2017 Programování 1-12 20