Procedurální programování,

Slides:



Advertisements
Podobné prezentace
Orbis pictus 21. století Tato prezentace byla vytvořena v rámci projektu.
Advertisements

Funkce Připomeňme si program pro výpočet faktoriálu:
Pascal - příklady.
Spojové struktury Spojová struktura ( linked structure ):
VISUAL BASIC Práce se soubory.
Metody (funkce, procedury)
ALGO – Algoritmizace 1. cvičení
Alg51 Rozklad problému na podproblémy Postupný návrh programu rozkladem problému na podproblémy –zadaný problém rozložíme na podproblémy –pro řešení podproblémů.
C# pro začátečníky Mgr. Jaromír Osčádal
Cvičení 2 Proměnné(jednoduché a složené) a konstanty První program Zápis výrazů.
Algoritmy I Cvičení č. 3.
Materiály k přednášce Úvod do programování Ondřej Čepek.
Medians and Order Statistics Nechť A je množina obsahující n různých prvků: Definice: Statistika i-tého řádu je i-tý nejmenší prvek, tj., minimum = statistika.
Větvení cykly J a v a Začínáme programovat Lucie Žoltá.
J a v a Začínáme programovat Lucie Žoltá. Odkazy - oficiální stránky (překladače, help, metody, vývojové prostředí NetBeans,...)
Vývojové diagramy a základy algoritmizace
Algoritmizace a programování
Vyučovací hodina 1 vyučovací hodina: Opakování z minulé hodiny 5 min Nová látka 20 min Procvičení nové látky 15 min Shrnutí 5 min 2 vyučovací hodiny: Opakování.
Informatika I 2. přednáška
A1PRG - Programování – Seminář Ing. Michal Operátory (2. část) 4 Verze
C – strukturované příkazy
Objektové programování
Gramatiky a jazyky Přednáška z předmětu Řízení v komplexních systémech
Ukázka odstranění rekurze Přemysl Tišer
Počítače a programování 1
Cvičení.
3. Příkazy  Příkazy dělíme na jednoduché a strukturované.  Jednoduché příkazy - žádnou jejich dílčí částí neni příkaz - přiřazovací, vstupu a výstupu,
5. Procedury a funkce Procedura je samostatně odladěný algoritmus, v programu může být volána vícekrát. Dvojí terminologie - rozlišujeme procedury a funkce.
Informatika I 7. přednáška RNDr. Jiří Dvořák, CSc.
Informatika I 8. přednáška RNDr. Jiří Dvořák, CSc.
ZADÁNÍ Sestavte program, který vypočítá obvod a obsah čtverce o straně a. Zajistěte, aby výpočet byl realizován pouze v případě, kdy strana a bude mít.
Dědičnost - inheritance dědičnost je jednou z forem znovupoužitelnosti dědičnost je jednou z forem znovupoužitelnosti B A Třída A je předkem třídy B Třída.
7. Typ soubor Souborem dat běžně rozumíme uspořádanou množinu dat, uloženou mimo operační paměť počítače (na disku). Pascalský soubor je abstrakcí skutečného.
Napište program v C pro výpočet plochy obdélníka se stranami A=3 a B=2. Výsledek vytiskněte s patřičným komentářem na obrazovku formátovým příkazem printf.
OSNOVA: a)Funkce – úvod b) Hlavičky funkcí c) Rekurze funkcí d)Knihovny funkcí e)Příklady Jiří Šebesta Ústav radioelektroniky, FEKT VUT v Brně Počítače.
Rozklad problému na podproblémy, rekurze
A1PRG - Programování – Seminář Ing. Michal Řízení běhu programu 5 Verze
1 Počítače a programování 1 13.přednáška. 2 Obsah přednášky Vstupy a výstupy – 1.část.
Počítače a programování 1 7.přednáška. Základy Pole ve třídách a metodách Pole Arrays.
Soubory BI-PA1 Programování a algoritmizace 1, ZS Katedra teoretické informatiky © Miroslav Balík Fakulta informačních technologií České vysoké.
Jazyk C A0B36PRI - PROGRAMOVÁNÍ Část II.
Pascal – strukturované příkazy
Jazyk C A0B36PRI - PROGRAMOVÁNÍ Část I.
Sylabus V rámci PNV budeme řešit konkrétní úlohy a to z následujících oblastí: Nelineární úlohy Řešení nelineárních rovnic Numerická integrace Lineární.
ÚPLNÁ PODMÍNKA V JAVĚ úkol 1_29.
Funkce, intuitivní chápání složitosti
Řízení běhu programu, řídící struktury A0B36PRI - PROGRAMOVÁNÍ
Úvod do programování Vyučující: Mgr. Vítězslav Jersák
PŘÍKAZ do - while úkol 1_43.
Programování v MATLABu © Leonard Walletzký, ESF MU, 2000.
Algoritmizace a programování Algoritmy 4 – Vývojové diagramy (cykly)
Algoritmizace a programování Algoritmy 1 - Úvod. Základní pojmy Počítačový program Počítačový program zápis zdrojového kódu, kterému rozumí počítač zápis.
Praha & EU: Investujeme do vaší budoucnosti Evropský sociální fond Gymnázium, Praha 10, Voděradská 2 Projekt OBZORY Datové typy a operátory Základní programové.
NÁZEV ŠKOLY: S0Š Net Office, spol. s r.o., Orlová-Lutyně AUTOR: Ing. Adéla Tomalová NÁZEV: Podpora výuky v technických oborech TEMA: Objektově orientované.
Moduly.
M2160 – Úvod do programování II
Programování ENUM, SWITCH,pole jednorozměrná a vícerozměrná, deklarace, inicializace, kopírování, porovnání Erik Král.
C# konzole – Podíl dvou čísel, podmínka IF
Výukový materiál zpracován v rámci projektu
Algoritmizace a programování
Vytváření dokumentace algoritmů
Rekurze.
Opakování základních příkazů a syntaxí v programovacím jazyce Pascal
Podprogramy.
Opakování ze 3. cvičení deklarace proměnných výpis na monitor (výstup)
C# přehled vlastností.
NÁZEV ŠKOLY: S0Š Net Office, spol. s r.o., Orlová-Lutyně
Opakování ze 4. cvičení int a; printf("Zadej číslo: ");
Algoritmizace a datové struktury (14ASD)
NÁZEV ŠKOLY: S0Š Net Office, spol. s r.o., Orlová-Lutyně
Transkript prezentace:

Procedurální programování, A0B36PRI - PROGRAMOVÁNÍ Procedurální programování, rekurze Jazyk JAVA České vysoké učení technické Fakulta elektrotechnická V 2.02

Procedurální programování - zásady Postupný návrh programu rozkladem řešeního problému na podproblémy zadaný problém rozložíme na podproblémy pro řešení podproblémů zavedeme abstraktní příkazy pomocí abstraktních příkazů sestavíme hrubé řešení abstraktní příkazy realizujeme pomocí metod (funkcí, procedur) Navržené metody propojíme pomocí předávání parametrů Rozklad problému na podproblémy ukážeme na jednoduchých příkladech A0B36PRI „PROGRAMOVÁNÍ“ 06

Rozklad problému na podproblémy Vstup dat od uživatele metodaA( ) Výstupní Parametr(y) Dílčí výpočet 1 metodaB( ) Vstupní parametry Řešený problém main() Začátek programu Konec programu metodaA ( ) metodaB ( ) metodaC ( ) metodaD ( ) Dílčí výpočet 2 metodaC( ) Výstup výsledku pro uživatele metodaD( ) Vstupní parametry A0B36PRI „PROGRAMOVÁNÍ“ 06

Příklad 1 – Výpočet s volbou metody Navrhněte řešení programu, který vypočítá buď obsah obdélníku nebo kruhu. Druh výpočtu lze volit z klávesnice z nabídkového menu (volba čisly) Výpočet lze spouštět z klávesnice opakovaně pro různé parametry Výsledky výpočtu se zobrazují na obrazovce Dílčí podproblémy (pro identifikované části zvolíme název budouci metody): Nabídkové menu s volbou obsluhy (1) ctiPrikaz Vykonání příkazu obsluhy (2) cmdObdelnik (3) cmdKruh Vlastní matematický výpočet (4) obsahObdelniku (5) obsahKruhu Pomocné metody Zjistění parametrů pro výpočet (6) prectiKladnyDouble Tisk nápovědy, pokynů a výsledků (7) tiskNaObrazovku Řídicí program celého řešení,zapíšeme v: (8) main Identifikovali jsem 8 dílčích bloků, ty zapíšeme pomocí metod A0B36PRI „PROGRAMOVÁNÍ“ 06

Příklad 1 – Výpočet s volbou metody Hrubé řešení (zapsané pseudojazykem – ten si volíme) Opakuj { switch (ctiPrikaz) pocitat-obdelnik: cmdObdelnik tiskNaObrazovku // napoveda prectiKladnyDouble // cti parametry vypoctu obsahObdelniku // vlastni vypocet tiskNaObrazovku // zobraz vysledek break pocitat-kruh: cmdKruh obsahKruhu // vlastni vypocet tiskNaObrazovku // zobraz vysledek konec-programu: return } A0B36PRI „PROGRAMOVÁNÍ“ 06

Příklad 1 – Vstup a vyhodnocení příkazu static int ctiPrikaz ( ) { Scanner sc = new Scanner(System.in); final int CMD_KRUH=1,CMD_OBDELNIK=2,CMD_KONEC=3;int cmd; while (true) { tiskNaObrazovku ("\nObsah-obdelniku=1,Obsah-kruhu=2,Konec=3","\n"); tiskNaObrazovku("Prikaz = ",""); switch(cmd = sc.nextInt()) { case CMD_KRUH:…; case CMD_OBDELNIK:..; case CMD_KONEC: return (cmd); default: tiskNaObrazovku("==Neznamy prikaz==","\n");break; } } } A0B36PRI „PROGRAMOVÁNÍ“ 06

Příklad 1 – Příkaz pro výpočet obsahu obdélníku static void cmdObdelnik ( ) { // Akce "Obdelnik" tiskNaObrazovku("Vypocet obsahu OBDELNIKU","\n"); // Vstup dat double a = prectiKladnyDouble("a ="); double b = prectiKladnyDouble("b ="); // Vypocet double p = obsahObdelniku(a, b); // Vystup dat tiskNaObrazovku("Obsah Obdelniku = ","",p); } A0B36PRI „PROGRAMOVÁNÍ“ 06

Příklad 1 – Příkaz pro výpočet obsahu kruhu static void cmdKruh ( ) { // Akce "Kruh" tiskNaObrazovku("Vypocet obsahu KRUHU","\n"); // Vstup dat double r = prectiKladnyDouble("r ="); // Vypocet double p = obsahKruhu(r); // Vystup dat tiskNaObrazovku("Obsah KRUHU = ","",p); } A0B36PRI „PROGRAMOVÁNÍ“ 06

Příklad 1 – Vlastní výpočet obsahů obrazců static double obsahObdelniku (double a, double b) { // Vypocet double obsahObdelniku = a * b; return (obsahObdelniku); } static double obsahKruhu (double r) { double obsahKruhu = 2 * Math.PI * r; return (obsahKruhu); A0B36PRI „PROGRAMOVÁNÍ“ 06

Příklad 1 – Zjištění parametrů výpočtu static double prectiKladnyDouble (String napis) { // Vstup dat (kladne racionalni cislo) Scanner sc = new Scanner(System.in); while (true) { tiskNaObrazovku("Zadej kladne cislo","\n"); tiskNaObrazovku(napis,""); double d = sc.nextDouble(); if (d >= 0) return(d); tiskNaObrazovku("Chyba","\n"); } A0B36PRI „PROGRAMOVÁNÍ“ 06

Příklad 1 – Tisk nápovědy a výsledků static void tiskNaObrazovku (String s,String lf,double d){ System.out.printf("%s%3.2f %s", s, d, lf); } static void tiskNaObrazovku (String s,String lf){ System.out.printf("%s %s", s, lf); Přetížené metody A0B36PRI „PROGRAMOVÁNÍ“ 06

Příklad 1 – Řídicí program celého řešení public class Main { static {Locale.setDefault(Locale.US);} public static void main(String[] args) { final int CMD_KRUH=1,CMD_OBDELNIK=2,CMD_KONEC=3; while (true) { switch ( ctiPrikaz() ) { case CMD_KRUH: cmdKruh();break; case CMD_OBDELNIK: cmdObdelnik();break; case CMD_KONEC: tiskNaObrazovku("KONEC","\n");return; } A0B36PRI „PROGRAMOVÁNÍ“ 06

Příklad 1 – Připomenutí „Scanner“,“printf“ Před použitím metod „Scanneru“ (čtení klávesnice) je nutné: importovat knihovní soubor java.util.* pokud chceme zadávat z klávesnice desetinou tečku (ne čárku) zapíšeme deklaraci: static {Locale.setDefault(Locale.US);}. Založit proměnnou sc (viz níže), proč bude vysvětleno v lekci o objektech. Před použitím „printf“ není nutné importovat žádnou knihovnu. import java.util.*; public class Main { static {Locale.setDefault(Locale.US);} metody ( ) { Scanner sc = new Scanner(System.in); int x = sc.nextIn t(); System.out.printf("%s%3.2f %s", s, d, lf); } } // class END A0B36PRI „PROGRAMOVÁNÍ“ 06

Příklad 2 – Hra NIM Navrhněte řešení programu pro hru NIM „počítač-člověk“ Pravidla hry NIM: hráč zadá počet zápalek (např. od 15 do 35) pak se střídá se strojem v odebírání; odebrat lze 1, 2 nebo 3 zápalky, prohraje ten, kdo odebere poslední zápalku. Dílčí podproblémy: zadání počtu zápalek odebrání zápalek hráčem odebrání zápalek strojem A0B36PRI „PROGRAMOVÁNÍ“ 06

Příklad 2 – Hra NIM Pravidla pro odebírání zápalek strojem, která vedou k vítězství (je-li to možné): počet zápalek nevýhodných pro protihráče je 1, 5, 9, atd., obecně 4n+1, kde n >0, stroj musí z počtu p zápalek odebrat x zápalek tak, aby platilo p – x = 4n + 1 z tohoto vztahu po úpravě a s ohledem na omezení pro x dostaneme x = (p – 1) mod 4 vyjde-li x=0, znamená to, že okamžitý počet zápalek je pro stroj nevýhodný a bude-li protihráč postupovat správně, stroj prohraje. A0B36PRI „PROGRAMOVÁNÍ“ 06

Příklad 2 – Hra NIM Hrubé řešení: int pocet; boolean stroj = false; // zadání počtu zápalek do{ if (stroj) “odebrání zápalek strojem“ else “odebrání zápalek hráčem“ stroj = !stroj; }while (pocet > 0); if (stroj) “vyhrál stroj“ else “vyhrál hráč“ Podproblémy „zadání počtu zápalek“, „odebrání zápalek strojem“ a „odebrání zápalek hráčem“ budeme realizovat metodami, proměnné pocet a stroj pro ně budou statickými (čili nelokálními) proměnnými A0B36PRI „PROGRAMOVÁNÍ“ 06

Příklad 2 – Hra NIM public class Nim { static int pocet; // aktuální počet zápalek static boolean stroj; // =true znamená, že bere počítač public static void main(String[] args) { zadaniPoctu(); stroj = false; // zacina hrac do { if (stroj) bereStroj(); else bereHrac(); stroj = !stroj; } while (pocet>0); if (stroj) System.out.println("vyhrál jsem"); else System.out.println ("vyhrál jste, gratuluji"); } static void zadaniPoctu() { … } static void bereHrac() { … } static void bereStroj() { … } A0B36PRI „PROGRAMOVÁNÍ“ 06

Příklad 2 – Hra NIM static void zadaniPoctu() { Scanner sc = new Scanner(System.in); do{ System.out.println("zadejte počet zápalek od15do 35)"); pocet = sc.nextInt(); }while (pocet<15 || pocet>30); } A0B36PRI „PROGRAMOVÁNÍ“ 06

Příklad 2 – Hra NIM static void bereHrac() { Scanner sc = new Scanner(System.in); int x; boolean chyba; do{ chyba = false; System.out.println( "počet zápalek " + pocet ); System.out.println( "kolik odeberete" ); x = sc.nextInt(); if(x < 1) { System.out.println( "prilis malo" ); chyba = true;} else if (x>3 || x>pocet) { System.out.println( "prilis mnoho");chyba = true;} }while(chyba); pocet -= x; } A0B36PRI „PROGRAMOVÁNÍ“ 06

Příklad 2 – Hra NIM static void bereStroj() { System.out.println( "počet zápalek " +pocet); int x = (pocet-1) % 4; if (x==0) x = 1; System.out.println( "odebírám " +x); pocet -= x; } A0B36PRI „PROGRAMOVÁNÍ“ 06

Rekurze Definice ze slovníku (pozor vtip) Rekurze viz „Rekurze“ ….nekonečná rekurze, lépe: pokud neznáte význam tohoto pojmu, pokračujte pojmem „Rekurze“ Rekurze - algoritmus, který volá v průběhu svého běhu sama sebe Příklad: výpočet faktoriálu: n! 0! = 1, 1! = 1, pro záporné číslo x budiž x! = 1 pro n>1, n! = n(n-1)! A0B36PR1 - 07

Rekurze Rekurzivní funkce (procedury) jsou přímou realizací rekurzivních algoritmů Rekurzivní algoritmus předepisuje výpočet „shora dolů“ v závislosti na velikosti (složitosti) vstupních dat: pro nejmenší (nejjednodušší) data je výpočet předepsán přímo pro obecná data je výpočet předepsán s využitím téhož algoritmu pro menší (jednodušší) data Výhodou rekurzivních funkcí (procedur) je jednoduchost a přehlednost Nevýhodou může být časová náročnost způsobená např. zbytečným opakováním výpočtu Řadu rekurzívních algoritmů lze nahradit iteračními, které počítají výsledek „zdola nahoru“, tj, od menších (jednodušších) dat k větším (složitějším) Pokud algoritmus výpočtu „zdola nahoru“ nenajdeme (např. při řešení problému Hanojských věží), lze rekurzivitu odstranit pomocí tzv. zásobníku A0B36PRI „PROGRAMOVÁNÍ“ 06

Rekurzivní algoritmus v některém kroku volá sám sebe Rekurzivní algorimus Rekurzivní algoritmus v některém kroku volá sám sebe Rekurzivní metoda v některém příkazu volá sama sebe ( i nepřímo ) Příklad – faktoriál : Rekurse n! = 1 pro n1 n! = n*(n-1)! pro n>1 Iterace n! = n*(n-1)*(n-2)*…*2*1 A0B36PRI „PROGRAMOVÁNÍ“ 06

Faktoriál pomocí rekurze a iterace n! = 1 pro n1 n! = n*(n-1)! pro n>1 Iterace n! = n*(n-1)*(n-2)*…*2*1 static int fakt(int n) { if (n<=1) return 1; return n*fakt(n-1); } static int fakt(int n) { if (n<=1) return 1; else return n*fakt(n-1); } static int fakt(int n) { int f = 1; while (n>1){ f *= n; n--; } return f; } static int fakt(int n) { return n<=1?1:n*fakt(n-1); // ternární operátor } A0B36PR1 - 07

Rekurze a rozklad problému na podproblémy Program, který přečte posloupnost čísel zakončenou nulou a vypíše ji obráceně Rozklad problému: zavedeme abstraktní příkaz přečti,vypiš a obrať posloupnost příkaz rozložíme do tří kroků: „obrať posloupnost“: přečti číslo (a ulož ho) if (přečtené číslo není nula) „obrať posloupnost“ (zbytek) vypiš číslo (uložené) A0B36PRI „PROGRAMOVÁNÍ“ 06

Příklad 3 - Rekurze „Obrať posloupnost“ přečti číslo if (přečtené číslo není nula) „obrať posloupnost, tj. zbytek“ vypiš číslo 2 cti x 4 if()… cti x 6 if()… cti x 8 if()… 2 4 6 8 0 0 8 6 4 2 cti x if()… cti x if()… 8 6 piš x 4 piš x piš x 2 piš x piš x A0B36PRI „PROGRAMOVÁNÍ“ 06

Příklad 3 - Rekurze – obrat() posloupnost Řešení: public class Obrat { static Scanner sc = new Scanner(System.in); public static void main(String[] args) { System.out.println("zadejte … zakončenou nulou"); obrat(); } static void obrat() { int x = sc.nextInt(); // načtení if(x!=0) obrat(); // otočení zbytku System.out.print(x + " "); // výpis uloženého A0B36PRI „PROGRAMOVÁNÍ“ 06

Příklad 4 - Rekurze - Hanojské věže Zavedeme abstraktní příkaz přenes_věž(n,1,2,3) který interpretujeme jako "přenes n disků z jehly 1 na jehlu 2 s použitím jehly 3". Pro n>0 lze příkaz rozložit na tři jednodušší příkazy přenes_věž(n-1,1,3,2) "přenes disk z jehly 1 na jehlu 2", přenes_věž(n-1,3,2,1) 1 2 3 A0B36PRI „PROGRAMOVÁNÍ“ 06 složitější

Příklad 4 - Rekurze - Hanojské věže public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println("zadejte výšku věže"); int pocetDisku = sc.nextInt(); prenesVez(pocetDisku, 1, 2, 3); } static void prenesVez (int vyska,int odkud,int kam,int pomoci){ if(vyska>0) { prenesVez(vyska-1, odkud, pomoci, kam); System.out.println("přenes disk z "+odkud+" na "+kam); prenesVez(vyska-1, pomoci, kam, odkud); 3 přenes disk z 1 na 2 přenes disk z 1 na 3 přenes disk z 2 na 3 přenes disk z 3 na 1 přenes disk z 3 na 2 A0B36PRI „PROGRAMOVÁNÍ“ 06 složitější

Příklad rekurze - Hanojské věže prenesVez(3, 1, 2, 3); prenesVez(2, 1, 3, 2); (1, 2); prenesVez(2, 3, 2, 1); prenesVez(1, 1, 2, 3); (1, 3); prenesVez(1, 2, 3, 1); | prenesVez(1, 3, 1, 2); (3, 2); prenesVez(1, 1, 2, 3); (1, 2); (2, 3); (3, 1); (1, 2); prenesVez(int vyska, int odkud, int kam, int pomoci) { if (vyska>0) { prenesVez(vyska-1, odkud, pomoci, kam); System.out.println("přenes disk z "+odkud+" na "+kam); prenesVez(vyska-1, pomoci, kam, odkud); } 3 přenes disk z 1 na 2 přenes disk z 1 na 3 přenes disk z 2 na 3 přenes disk z 3 na 1 přenes disk z 3 na 2 A0B36PR1 - 07 složitější

Obecně k rekurzivitě Rekurzivní metody jsou přímou realizací rekurzivních algoritmů Rekurzivní algoritmus předepisuje výpočet „shora dolů“ v závislosti na velikosti (složitosti) vstupních dat: pro nejmenší ( nejjednodušší ) data je výpočet předepsán přímo pro obecná data je výpočet předepsán s využitím téhož algoritmu pro menší ( jednodušší ) data Výhodou rekurzivních metod je jednoduchost a přehlednost Nevýhodou může být časová náročnost způsobená např. zbytečným opakováním výpočtu A0B36PRI „PROGRAMOVÁNÍ“ 06

Fibonacciho posloupnost - historie Maatraameru (Chhandah-shāstra, the Art of Prosody, 450 or 200 BC) Leonardo Pisano (Leonardo z Pisy), známý také jako Fibonacci (cca 1175–1250) - králíci Henry E. Dudeney (1857 - 1930) - krávy „Jestliže každá kráva vyprodukuje své první tele (jalovici) ve věku dvou let a poté každý rok jednu další jalovici, kolik budete mít krav za 12 let, jestliže Vám žádná nezemře?“ Rok - počet krav (jalovic) 1 1 2 1 3 2 4 3 5 5 6 8 ….. 12 144 50 20 365 011 074 (20 miliard) Počet krav = počet krav vloni + počet narozených (odpovídá počtu krav předloni) fn = fn-1 + fn-2 A0B36PR1 - 07

Fibonacciho posloupnost - rekurzivně Platí: f0 = 1 f1 = 1 fn = fn-1 + fn-2 pro n > 1 Rekurzivní funkce: static int fib(int i) { if (i<2) return 1; return fib(i-1)+fib(i-2); } Rekurze je hezká - zápis „odpovídá“ rekurentní definici. Je ale i efektivní? A0B36PR1 - 07

Složitost výpočtu Fibonacciho čísla - rekurzivně Příklad pro fib(10): fib(10) fib(9) + fib(8) + fib(8) fib(7) fib(7) + fib(6) fib(7) + fib(6) fib(6) + fib(5) fib(6) fib(5) fib(5) + fib(4) + f50 20 365 011 074 (20 miliard) Složitost je exponenciální!!!! static int fib(int i) { if (i<2) return 1; return fib(i-1)+fib(i-2); } A0B36PR1 - 07

Fibonacciho posloupnost - iteračně Platí: f0 = 1 f1 = 1 fn = fn-1 + fn-2 ,pro n > 1 Iteračně: static int fib(int n) { int i, fibNMinus2=1; int fibNMinus1=1, fibN=1; for (i=2; i<=n; i++) { fibNMinus2 = fibNMinus1; fibNMinus1 = fibN; fibN = fibNMinus1 + fibNMinus2; } return fibN; fibNMinus2 fibNMinu1 fibN i 1 1 1 1 + 1 2 2 1 + 2 3 3 2 + 3 5 4 3 + 5 8 5 Složitost: 3*n A0B36PR1 - 07

Složitost výpočtu Fibonacciho čísla 2 Iterační metoda: 3*n Rekurzivní výpočet ~ 2n Podíl dvou po sobě následujících členů konverguje k hodnotě „zlatého řezu“ (Johannes Kepler - golden ratio): φ ≈1,6180339887498948482045868343656 Zlatý řez byl pokládán za středověku za ideální proporci mezi různými délkami Zlatý řez vznikne rozdělením úsečky na dvě části tak, že poměr větší části k menší je stejný jako poměr celé úsečky k větší části A0B36PR1 - 07 Pro zájemce

Další příklady rekurze - fraktály A0B36PR1 - 07 Pro zájemce

Příklad rekurze, základní schéma – součin public static void main(String[] args) { int x,y; ……; System.out.println(" " + souI(x, y) + souR(x,y)); } static int souI(int s, int t){ int souI=0; for (int i = 0; i < s; i++) souI=souI+t; return souI; static int souR(int s, int t) { int souR; if (s > 0)souR=souR(s - 1,t)+t; else souR = 0; return souR; } A0B36PR1 - 07

Shrnutí a perspektiva Naivní styl Procedurální styl Objektový přístup, malý úvod bude Návrhové vzory, další studium A0B36PRI „PROGRAMOVÁNÍ“ 06

Programovací styly Na příkladu programu simulujícího čítač si ukážeme programovací styly: naivní procedurální objektově orientovaný (viz přednáška „Úvod do objektově orientovaného programování") Příklad komunikace programu: Hodnota = 10 0) Konec 1) Zvětši 2) Zmenši 3) Nastav Vase volba: 1 Hodnota = 11 0) Konec 1) Zvětši 2) Zmenši 3) Nastav ... A0B36PRI „PROGRAMOVÁNÍ“ 06

Naivní styl Jednoduché úlohy lze řešit přímočaře: import java.util.*; public class Citac1 { final static int pocHodn = 0; static int hodn, volba; public static void main(String[] args) { Scanner sc = new Scanner(System.in); hodn = pocHodn; do{ System.out.prinln( "Hodnota = " + hodn ); System.out.println ( "0) Konec\n1) Zvětši\n2) Zmenši\n3) Nastav" ); System.out.print( "Vaše volba: " ); volba = sc.nextInt(); switch ( volba ) { case 0: break; case 1: hodn++; break; case 2: hodn--; break; case 3: hodn = pocHodn; break; default: System.out.println( "nedovolená volba" ); } }while (volba > 0); System.out.println( "Konec" ); A0B36PRI „PROGRAMOVÁNÍ“ 06

Procedurální styl Připomeňme hlavní zásady: Zadaný problém se snažíme rozložit na podproblémy Pro řešení podproblémů zavádíme abstraktní příkazy, které nejprve specifikujeme a pak realizujeme pomocí metod Aplikováno na "čítač" identifikujeme tyto dílčí podproblémy: komunikace s uživatelem, jejímž výsledkem je kód požadované operace provedení požadované operace s čítačem Řešení: public class Citac2 { final static int POC_HODN = 0; // třídní konstanta static int hodn; // třídní proměnná static void operace(int op) { // pro všechny 3 operace switch (op) { case 1: hodn++; break; case 2: hodn--; break; case 3: hodn = POC_HODN; break; } A0B36PRI „PROGRAMOVÁNÍ“ 06

Procedurální styl static int menu(){ Scanner sc = new Scanner(System.in); int volba; do { System.out.println( "0. Konec" ); System.out.println( "1. Zvětši" ); System.out.println( "2. Zmenši" ); System.out.println( "3. Nastav" ); System.out.print( "Vaše volba: " ); volba = sc.nextInt(); if (volba < 0 || volba > 3){ System.out.println( "nedovolená volba" ); volba = -1; } }while (volba < 0); return volba; A0B36PRI „PROGRAMOVÁNÍ“ 06

Procedurální styl Poznámky: public static void main(String[] args) { int volba; hodn = POC_HODN; do{ System.out.println("hodnota = " +hodn); volba = menu(); if (volba>0) operace(volba); } while (volba > 0); System.out.println("Konec"); } Poznámky: procedurální řešení čítače (jediná procedura pro všechny operace, třídní proměnná pro hodnotu, třídní konstanta udávající počáteční hodnotu) je nedokonalé (proč?) čítač je typ, pro který jsou definovány určité operace (realizované metodami) a jehož implementace (proměnná pro hodnotu) by neměla být volně přístupná tedy pro realizaci čítače je vhodnější objektově orientovaný styl (nebo lokální statická proměnná – viz úvod do jazyka "C"). A0B36PRI „PROGRAMOVÁNÍ“ 06

Shrnutí Další informace k této přednášce hledejte např. v: Herout, P.: Učebnice jazyka Java, Kopp, Č.Budějovice, 2010, str.114 – 128.

Procedurální programování A0B36PRI - PROGRAMOVÁNÍ Procedurální programování a rekurze Jazyk JAVA Konec České vysoké učení technické Fakulta elektrotechnická