Obsah 2. přednášky: Terminálový formátovaný výstup Problémy při provádění aritmetických operací Řídicí struktury - úvod Větvení - příkazy if, if-else (else if), switch Cykly - příkazy while, for, do-while Příkazy break a continue Algoritmizace postup řešení jednoduchého problému (ACM) Tato tematika je zpracována v Záznamy přednášek: str. 34-36, 44-61 Problém: Je dán počet testovaných případů t (1 t 100) a pro každý takový případ je na samostatném řádku zadáno celé číslo n (-1000 n 1000). Pro všechna zadaná n spočtěte a na samostatném řádku vypište výsledek následujícího úkolu: Vynásobte číslo n 567mi, poté vydělte výsledek 9, přičtěte 7492, pak vynásobte 235, výsledek vydělte 47 a odečtěte 498. Jaká číslice je ve vypočtené hodnotě na řádu desítek? Postup řešení je uveden na konci této přednášky. Přednášky KIV/PPA1, A. Netrvalová, 2016 2. přednáška
Terminálový formátovaný výstup terminálový velmi primitivní výstup (obrazovka - txt režim) formátovaný čísla na výstupu automaticky převedena na řetězec číslic v desítkové soustavě 1. Klasický výstup System.out.print(parametr), System.out.println(), System.out.println(parametr) print(parametr) metoda třídy System, pro výstup parametr primitivní typ nebo řetězec funkce - pro každý primitivní typ existuje implicitní konverze na řetězec int i=1; System.out.print ("i = " +i); // i = 1 System.out.println('A'); // i = 1A System.out.println(Math.E); // 2.718281828459045 System.out.println(5); // 5 System.out.println(5.25); // 5.25 System.out.println("Hello world\n"); // "\n" odradkovani // ALE POZOR: prevod na typ prvniho vystupu (tj. na int) System.out.println(5 + i + 'A'); /* 5+1+65 = 71 (65=kod pismena A) nutno na zacatek umistit prazdny retezec */ System.out.println("" + 5 + i + 'A'); // 51A ok! // JESTE jednou POZOR: chci soucet i+2, System.out.println("index = " + i + 2); // ale vypis je 12 nutno uzavrit do zavorek System.out.println("index = " + (i+2)); // 3 ok! Strana 2 (celkem 32)
2. Lepší řešení výstupu (od JDK 1.5) Použití metody - System.out.format(parametr) pozor: parametry jsou odděleny, (čárkou) nikoliv + Používat jen, je-li to nutné! Více informací: Záznamy přednášek (str. 36 38) + java.util.formatter Základní pravidla: - ve formátovacím řetězci - za znakem % formátovací znaky - kolik je znaků %, tolik dalších parametrů int i = 1, sum = 33; System.out.format("i = %d, suma = %d%n", i, sum); // i = 1, suma = 33 Poznámka: Desetinný oddělovač je závislý na lokalitě pro ČR je to čárka, pro US tečka (viz dále). Výpis celého čísla v desítkové soustavě - používá se %d, např. pro int i = -1234; System.out.format("i = %d%n", i); // i = -1234 - počet míst lze stanovit, pak se doplňují mezery zleva, tj. zarovnání doprava, např.: System.out.format("i = %7d%n", i); // i = -1234 - počet míst lze stanovit a zarovnat doleva (zbylé místo se doplní mezerami), např.: System.out.format("i = %-7dahoj%n", i); // i = -1234 ahoj - lze vynutit výpis i + znaménka, např. pro int i = 1234; System.out.format("i = %+7d%n", i); // i = +1234 - vynutí se výpis nevýznamových nul, např.: System.out.format("i = %07d%n", i); // i = -001234 - vypisuje se i oddělovač řádů, např.: System.out.format("i = %,7d%n", i); // i = -1 234 Strana 3 (celkem 32)
Výpis celého čísla v jiných soustavách - osmičková soustava, např. pro int j = 30; System.out.format("j = %o%n", j); // j = 36 - šestnáctková soustava, např. pro int j = 30; System.out.format("j = %X%n", j); // j = 1E - počet míst lze určit, např.: System.out.format("j = %3X%n", j); // j = 1E - lze vynutit nevýznamové nuly, např. pro: int j = 10; System.out.format("j = %02X%n", j); // j = 0A Výpis znaku - používá se %c, např. pro char c = 'a'; System.out.format("c = %c%n", c); // c = a - lze použít přetypování a lze vypsat více proměnných najednou System.out.format("Znak %c ma ASCII hodnotu: %d%n", c, (int) c); // Znak a ma ASCII hodnotu: 97 Výpis reálného čísla (od verze Java 1.7 všude znak:,) - reálné číslo %f, např. pro double d = 1234.567; System.out.format("d = %f%n", d); // d = 1234,567000 - výpis ve vědeckotechnické notaci %g, %e např. pro: double d = 1234.567; System.out.format("d = %g%n", d); // d = 1234,57 System.out.format("d = %e%n", d); // d = 1,234567e+03 - lze nastavit počet míst celkem (10) a počet míst za desetinným oddělovačem (1), číslo bude zaokrouhleno System.out.format("d = %10.1f%n", d); // d = 1234,6 - lze použít zarovnání doleva, výpis nevýznamových nul, oddělovač řádů apod. stejně jako u celého čísla Strana 4 (celkem 32)
Výpis řetězce - používá se %s, např. pro String s = "Ahoj lidi"; System.out.format("s = %s%n", s); // s = Ahoj lidi - řetězec lze vypsat velkými písmeny System.out.format("s = %S%n", s); // s = AHOJ LIDI - lze stanovit šířku výpisu, výpis bude zarovnán doprava System.out.format("s = %11s %n", s); // s = Ahoj lidi - výpis lze zarovnat i doleva System.out.format("s = %-11s %n", s); // s = Ahoj lidi Příklad (program + výstup): public class FormatovaniVystupu { public static void main(string [] args) { System.out.format("nova radka%n"); int i = -1234; System.out.format("i = %d%n", i); System.out.format("i = %7d%n", i); System.out.format("i = %-7d%n", i); System.out.format("i = %+7d%n", i); System.out.format("i = % 7d%n", i); System.out.format("i = %07d%n", i); System.out.format("i = %, 7d%n", i); char c = 'a'; System.out.format("c = %c%n", c); System.out.format("c = %3c%n", c); System.out.format("c = %C%n", c); System.out.format("c = %c%n", c); System.out.format("c = %c%n", 65);... pokračování na dalším slidu Strana 5 (celkem 32)
double d = 1234.567; System.out.format("d = %f%n", d); System.out.format("d = %g%n", d); // zmena v java 1.7 System.out.format("d = %e%n", d); // zmena v java 1.7 System.out.format("d = %10.1f%n", d); System.out.format("d = %-10.1f%n", d); int j = 30; System.out.format("j = %o%n", j); System.out.format("j = %x%n", j); System.out.format("j = %X%n", j); System.out.format("j = %3X%n", j); System.out.format("j = %#x%n", j); String s = "ahoj lidi"; System.out.format("s = %s %n", s); System.out.format("s = %S %n", s); System.out.format("s = %11s %n", s); System.out.format("s = %-11s %n", s); System.out.format("s = %.3s %n", s); System.out.format("s = %11.3s %n", s); System.out.format("Pivo \"lezak\" ma 12%%%n"); System.out.format("Znak 'backslash' je \\%n"); j = 30; System.out.format("%d = %o = %X%n", j, j, j); System.out.format("%1$d = %1$o = %1$X%n", j); System.out.format("%d = %<o = %<X%n", j); String zformatovanyretezec = String.format ("%6d", 123); System.out.println(zformatovanyRetezec); String hexcislo = "1A"; int cislo = Integer.parseInt(hexCislo, 16); System.out.format("%s H = %d D = %o O%n", hexcislo, cislo, cislo); System.out.println("konec"); Strana 6 (celkem 32)
nova radka i = -1234 i = -1234 i = -1234 i = -1234 i = -1234 i = -001234 i = -1 234 c = a c = a c = A c = a c = A d = 1234,567000 d = 1234.57 // od verze 1.7: 1234,57 d = 1.234567e+03 // od verze 1.7: 1,234567e+03 d = 1234,6 d = 1234,6 j = 36 j = 1e j = 1E j = 1E j = 0x1e s = ahoj lidi s = AHOJ LIDI s = ahoj lidi s = ahoj lidi s = aho s = aho Pivo "lezak" ma 12% Znak 'backslash' je \ 30 = 36 = 1E 30 = 36 = 1E 30 = 36 = 1E 123 1A H = 26 D = 32 O konec Od verze Java 1.7 se u formátů reálných čísel v System.out.format() zobrazuje vždy desetinná čárka. Strana 7 (celkem 32)
Jak tedy zobrazit ve formátovaném výstupu desetinnou tečku? Použijeme třídu Formatter (obdobně jako Scanner) Výpis se pak volá stejně jako System.out.format, jen místo System.out se použije objekt Formatteru import java.util.*; public class PouzitiFormatter { // import java.util.formatter; Formatter f = new Formatter(System.out, Locale.US); //US //Formatter f = new Formatter(System.out); //CZ public static void main(string [] args){ double d = 1234.567; f.format("d = %f%n", d); f.format("d = %g%n", d); f.format("d = %e%n", d); f.format("d = %10.1f%n", d); f.format("d = %-10.1f%n", d); f.close(); // nutno uzavrit Výpisy - v US lokalizaci: d = 1234.567000 d = 1234.57 d = 1.234567e+03 d = 1234.6 d = 1234.6 V CZ lokalizaci (tj. bez nastavení lokalizace): d = 1234,567000 d = 1234,57 d = 1,234567e+03 d = 1234,6 d = 1234,6 Strana 8 (celkem 32)
Problémy při provádění arit. operací Důvod - zobrazení čísel, zaokrouhlování, Vysvětlení viz kódování. 1. Přetečení a podtečení (čísla, exponentu) Je-li výsledná absolutní hodnota: větší než max. zobrazitelná dojde k přetečení menší než min. zobrazitelná dojde k podtečení přetečení podtečení přetečení -max -min 0 +min +max Náprava pokud lze - zvětšit rozsah (změnit datový typ) 2. Porovnání dvou reálných čísel double x, y; x == y!! takto NE!!! upravit prostřednictvím <=, >= if (x == y) nahradit if (Math.abs(x - y) < ε) kde: ε absolutní chyba porovnání 3. Problém zaokrouhlení Nevhodným řazením operací s řádově odlišnými hodnotami čísel, opakováním výpočtů v cyklech, atd. může docházet i k výrazným numerickým chybám System.out.println("" + (1.2E200 + 1E100)); System.out.println("" + (0.000123456789012345 + 1)); System.out.println("" + ((43.1-43.2) + 1.)); // = 0.9 double s = 0; for (int i=0; i<10000; i++) s += 0.0001; System.out.println("" + s); // = 1.0 1.2E200 1.0001234567890123 0.8999999999999986 0.9999999999999062 Strana 9 (celkem 32)
Řídicí struktury - úvod - složený příkaz (sekvence) - blok příkazů - větvení sekvence (selekce) - podmínky - opakování sekvencí (iterace) - cykly 1. Blok n příkazů P1 P2 Pn { Zápis v jazyce JAVA { P 1 ;. P. n ; int cislo1 = 0; int cislo2 = 3; int sum = cislo1 + cislo2; 2. Větvení programu Zápis v jazyce JAVA Blok příkazů 1 + - Blok příkazů podmínka Blok příkazů 2 + podmínka - if (PODMÍNKA) { BLOK PŘÍKAZŮ 1; else { BLOK PŘÍKAZŮ 2; int cislo = -5; boolean prirozene; if (cislo > 0) { prirozene = true; cislo = cislo -1; else { prirozene = false; cislo = cislo +1; Strana 10 (celkem 32)
3. Příkaz výběru z více možností 2,4,6,8 selektor 1,3,5,7,9.. 0 Příkaz 1 Příkaz 2 Příkaz N část else.. Zápis v jazyce JAVA switch (VÝRAZ) { case HODNOTA1: PŘÍKAZ1; break;... case HODNOTA_N: PŘÍKAZ_N; break; default: PŘÍKAZ_DEF; break; switch (cislo) { case 0: System.out.println( nula ); break; case 2: case 4: case 6: case 8: System.out.println( suda cislice ); break; default: System.out.println( licha cislice,zaporne cislo,cislo >9 ); break; Strana 11 (celkem 32)
Java 1.7 je možno použít řetězec v příkazu switch Scanner sc = new Scanner (System.in); System.out.print("Zadej den v tydnu: "); String denvtydnuarg = sc.nextline(); String typdne; switch (denvtydnuarg) { case pondeli : typdne = Zacatek tydne ; System.out.println( Typ dne( + denvtydnuarg + ): + typdne); break; case utery : case streda : case ctvrtek : typdne = Den uprostred tydne ; System.out.println( Typ dne( + denvtydnuarg + ): + typdne); break; case patek : typdne = Konec pracovniho tydne ; System.out.println( Typ dne( + denvtydnuarg + ): + typdne); break; case sobota : case nedele : typdne = Vikend ; System.out.println( Typ dne( + denvtydnuarg + ) : + typdne); break; default: System.out.println( Spatne zadany den: + denvtydnuarg); break; Poznámka: Typ String viz třída String (bude v 6. (7) přednášce) Strana 12 (celkem 32)
4. Cyklus se známým počtem opakování pro i 1. n Zápis v jazyce JAVA Blok příkazů 5. Cyklus s podmínkou na začátku podmínka + Blok příkazů - int sum = 0; for (int i = 0; i<10; i++) { sum = sum + i; int max = 5; int sum = 0; while (sum < max) { sum = sum + 1; for(int i = 1; i<=n; i++) { BLOK PŘÍKAZŮ; Zápis v jazyce JAVA while (PODMÍNKA) { BLOK PŘÍKAZŮ; 6. Cyklus s podmínkou na konci Blok příkazů podmínka + - Zápis v jazyce JAVA do { BLOK PŘÍKAZŮ; while (PODMÍNKA); int prvni = 4; int druhe = 8; do { int zbytek = prvni % druhe; prvni = druhe; druhe = zbytek; while(druhe!= 0); Strana 13 (celkem 32)
Větvení - příkazy if, if-else (else if), switch - realizuje více variant dalšího postupu Ilustrační příklad (pozor na strukturu zápisu) if (x > 5){ // prikaz IF System.out.println(x + " > 5"); if (x > 5){ // prikaz IF-ELSE System.out.println(x + " > 5"); else { System.out.println(x + " <= 5"); if (x > 5){ // prikaz ELSE-IF System.out.println(x + " > 5"); else { if (x < 5) { System.out.println(x + " < 5"); else { System.out.println(x + " = 5"); switch (x) { // prepinac case 0: case 1: case 2: case 3: case 4: System.out.println(x + " : x < 5"); break; case 5: System.out.println(x + " :x = 5"); break ; case 6: case 7: case 8: case 9: System.out.println(x + " : x > 5"); break ; default: System.out.println(x + " :x neni cislice!"); break; Strana 14 (celkem 32)
Příklad: import java.util.*; /** * Precte tri strany trojuhelnika a vypocita obsah, pokud * strany tvori trojuhelnik */ public class Trojuhelnik { private static Scanner sc = new Scanner(System.in); public static void main(string[] args) { sc.uselocale(locale.us); System.out.print("Zadej stranu a: "); double a = sc.nextdouble(); System.out.print("Zadej stranu b: "); double b = sc.nextdouble(); System.out.print("Zadej stranu c: "); double c = sc.nextdouble(); if (((a+b)>c) && ((b+c)>a) && ((a+c)>b))) { double s =(a + b + c)/2; double obsah =Math.sqrt(s*(s-a)*(s-b)*(s-c)); System.out.println("O = " + obsah); else { System.out.println("Strany netvori trojuhelnik."); Zadej stranu a:3 Zadej stranu b:4 Zadej stranu c:5 O = 6.0 Poznámka: Ternární výraz: promenna = podminka? vyraz1 : vyraz2; (používá se málo) int a = 2, b = 4; int vetsi = (a>b)? a : b; Strana 15 (celkem 32)
Při používání příkazu if (ve všech modifikacích) dochází velmi často k chybám (nejen v gramatice, ale i v logice). Příklad chybného použití Zadání: Máme dvě celočíselné proměnné x a y. Pokud bude x=0, zvětšíme x o 1. Pokud bude y=0, zvětšíme y o 1. Pokud budou hodnoty x a y zároveň nula, obě snížíme o 1. (Pro x=0 a y=0 nebude příklad vlevo fungovat!) int x = 0; // CHYBNE!!! int y = 0; if (x == 0){ x++; // x = 1 System.out.println("x=" + x); if (y == 0){ y++; // y = 1 System.out.println("y=" + y); if (x == 0 && y == 0){ /* nezabere x nebo y uz není 0 */ x--; y--; System.out.print ("x=" + x); System.out.println (", y=" + y); Více informací a příkladů v Záznamech přednášek! int x = 0; int y = 0; // SPRAVNE if (x == 0 && y == 0){ x--; y--; System.out.print("x=" + x); System.out.println(", y=" + y); else { if (x == 0) { x++; System.out.println("x=" + x); else { if (y == 0) { y++; System.out.println("y=" + y); /* vyreseno pouzitim ELSE IF a prehozenim poradi podminek */ Strana 16 (celkem 32)
Cykly - příkazy while, for, do-while - realizuje opakování sekvence kódu - problém nekonečného cyklu Pojmy - hlavička a tělo cyklu - proměnná cyklu - podmínka ukončení cyklu Příklady použití cyklů a vznik nekonečných cyklů final int KONST = 5; int a = 0; while(a < KONST) { // a se musi v cyklu menit! a++; // vypusteni predchozi radky = nekonecny cyklus System.out.println(" " + a); for (int i = 3; i < KONST; i++) { // nerovnost plati stale // i-- zpusobi nekonecny cyklus a--; System.out.println(" " + a); int sum = 0; a = 3; // a = 0; zpusobi nekonecny cyklus do { System.out.println("sum=" + sum); sum += a; while (sum < KONST); // a = 0 sum se nemeni Strana 17 (celkem 32)
Dostupnost proměnné cyklu for mimo cyklus /* misto for(int i=0;... pouzit jen for(i=0;... a nad cyklem deklarovat: int i;, ale pouzivat uvazene a obezretne! */ int i; for (/*int */ i = 0; i < 3; i++) { System.out.println ("i = " + i); // dostupna uvnitr cyklu System.out.println ("i = " + i); // i vne cyklu DOSTUPNA! Pozor na chybu při změně proměnné cyklu v těle cyklu for! int suma = 0; for (int i = 0; i < 7; i++) { i = i*3; // není ok, hodnotu promenne nemenit!!! suma = suma + i; System.out.println("i=" + i + ", suma=" + suma); Vnořené cykly for (int i = 1; i < 3; i++) { for (int j = 1; j < 3; j++) { System.out.println (i + " " + j); for (int i = 1; i < 3; i++) { int j = 1; while (j < 4) { j++ System.out.println (i + " " + j); Více proměnných cyklu 1 1 1 2 2 1 2 2 1 2 1 4 2 2 2 4 for(int i = 0, j = 1; i < 10 && j!= 11; i++, j++){ System.out.println (i + " " + j); // nepouzivat neprehledne! i=0, suma=0 i=3, suma=3 i=12, suma=15 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 Strana 18 (celkem 32)
Typické použití jednotlivých typů cyklů 1. cyklus for Spočtěte součet n prvních přirozených čísel int n = 5; int suma = 0; for (int i = 1; i <= n; i++) { suma += i; // n*(n+1)/2.0 suma = 15 2. cyklus while Sčítejte zadaná čísla, dokud není zadána 0. Scanner sc = new Scanner(vstup); String vstup = "1 2 3 4 5 0 6 7 8 9 10"; int sum = 0; int cislo; while((cislo = sc.nextint())!= 0) { sum += cislo; sum = 15 3. cyklus do Vypisujte zadaná čísla a výpis ukončete prvním číslem větším než max. int max = 7, zadano; // vstup - pokracuje z predchoziho prikladu do { zadano = sc.nextint(); System.out.print(" " + zadano); while(zadano <= max); 6 7 8 Strana 19 (celkem 32)
Další ukázky Příklad: postupné sčítání zadávaných čísel 1. varianta // postupne scitani, // ukonci scitani jakmile je soucet >= zadane sume System.out.print("Zadej sumu: "); int zadanasuma = sc.nextint(); int postupnysoucet = 0; while(postupnysoucet < zadanasuma) { System.out.print("Zadej cislo: "); postupnysoucet += sc.nextint(); System.out.println("soucet = " + postupnysoucet); Zadej sumu: 5 Zadej cislo:3 Zadej cislo:4 soucet = 7 2. varianta // postupne scitani, dokud je zadavano cislo int postupnysoucet = 0; System.out.print("Zadej cislo: "); while(sc.hasnextint()) { // testuje, je-li na vstupu cislo postupnysoucet += sc.nextint(); System.out.println("soucet = " + postupnysoucet); System.out.print("Zadej cislo: "); Zadej cislo:2 Zadej cislo:4 Zadej cislo:x soucet = 6 Strana 20 (celkem 32)
Praktický příklad 1: NSD Klempíř má rozstříhat pás plechu o rozměrech x [cm] a y [cm] na co největší čtverce tak, aby nevznikl žádný odpad. Vypočítejte velikost strany jednoho čtverce. Řešením je výpočet největšího společného dělitele NSD přirozených čísel a, b je číslo d takové, že: - čísla a i b jsou dělitelná číslem d - d je největší číslo splňující předchozí podmínku Hledání NSD: matematika - rozklad na prvočinitele Př.: x = 380 = 2. 190 = 2. 2. 5. 19 y = 60 = 2. 2. 3. 5 NSD ( 380; 60 ) = 2. 2. 5 = 20 příliš složité (hledání a testování prvočísel), programování používá tzv. Eukleidův algoritmus. Eukleidés, Euklides (325 př. n. l. 260 př. n. l) - řecký matematik a geometr. Většinu života strávil v Alexandrii v Egyptě. Jednoduché řešení odečítáním: vstup: a,b opakuj dokud a b od většího z čísel a, b odečti menší a výsledek ulož tam, kde bylo větší číslo výstup: a (nebo b, je to jedno, neboť a = b) Strana 21 (celkem 32)
Odstranění opakovaného odečítání (např. a>>b) - nahradit operací modulo (zbytek po celočíselném dělení). Výpočet je pak ukončen, pokud b = 0! Eukleidův algoritmus: 1. najdi: zbytek z - operace a%b 2. přesun: a b, b z 3. testuj: b 0 pokračuj: 1. b = 0 a je NSD konec import java.util.*; // cyklem while // Nejvetsi spolecny delitel dvou prirozenych. cisel public class NsdCyklusWhile { private static Scanner sc = new Scanner(System.in); public static void main(string[] args) { System.out.print("Zadej a: "); int a = sc.nextint(); System.out.print("Zadej b: "); int b = sc.nextint(); System.out.print("NSD(" + a + "," + b + ") = "); while (b!= 0) { int zbytek = a % b; a = b; b = zbytek; System.out.println(a); Příklad: 6 4 z = 2 a = 4 b = 2 z = 0 a = 2 b = 0 NSD = a = 2 Zadej a: 12 Zadej b: 8 NSD(12, 8) = 4 Strana 22 (celkem 32)
// cyklem do //. System.out.print("NSD(" + a+ "," + b + ") = "); do { int zbytek = a % b; a = b; b = zbytek; while(b!= 0); System.out.println(a); //. Zadej a: 36 Zadej b: 24 NSD(36,24) = 12 I následujícím způsobem - využitím cyklu for lze algoritmus realizovat, ale rozhodně to není typická realizace! // cyklem for //. System.out.print("NSD(" + a + "," + b + ") = "); for(; b!= 0;) { int zbytek = a % b; a = b; b = zbytek; System.out.println(a); //. Zadej a: 17 Zadej b: 7 NSD(17,7) = 1 Strana 23 (celkem 32)
Praktický příklad 2: Fibonacciho posloupnost 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55,... Již dříve (před Fibonaccim) indičtí učenci Gopāla (1135?), Hemacandra (1150?) - obdobná posloupnost (1,2,3,5,8,13,...) Leonardo Fibonacci (Filius Bonaccii) Leonardo z Pisy (1180? - 1250) Liber Abaci [1202] uveřejněna úloha: Sčítání králíků Kolik párů králíků se rozmnoží z jediného páru za jeden rok? Platí následující předpoklady: - každý pár zplodí každý měsíc nový pár - nový pár začíná rodit ve věku 1 měsíce - králíci neumírají E. Léger (1837) - využití Fibonacciho posloupnosti ke studiu efektivity Eukleidova algoritmu (viz sl. 13). Pokud čísla a, b nejsou větší než F k pak krok č. 2 proběhne nejvýše k+1-krát. Zlatý řez (Feidias - Φ - sochy, poměr Φ:1) Simon Jacob (1564): F n+1 /F n = ½(1+ 5 ) = Φ Strana 24 (celkem 32)
Fibonacciho posloupnost: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55,... f0 = 0, f1 = 1, f2 = f0 + f1, f3 = f1 + f2,... Obecně: f(0) = 0, f(1) = 1, f(i) = f(i-2) + f(i-1) pro i = 2, 3, 4,... public class FibonacciCyklemVypis { private static Scanner sc = new Scanner(System.in); public static void main(string args[]) { System.out.print("Zadej n: "); int n = sc.nextint(); int f0 = 0, f1 = 1; System.out.println("f" + 0 + " = " + f0); if(n >= 1){ System.out.println("f" + 1 + " = " + f1); for(int i=2; i<n; i++){ int f2 = f0 + f1; System.out.println("f" + i + " = " + f2); f0 = f1; f1 = f2; // pro prvních 10 clenu, nulou pocinajic Zadej n: 10 f0 = 0 f1 = 1 f2 = 1 f3 = 2 f4 = 3 f5 = 5 f6 = 8 f7 = 13 f8 = 21 f9 = 34 Strana 25 (celkem 32)
Praktický příklad 3: Výpočet třetí odmocniny * Spočteme reálny kořen binomické rovnice x 3 - a = 0, kde a je číslo, jehož třetí odmocninu hledáme. Použijeme vzorec Newtonovy metody: x[i+1]=x[i]-f(x[i])/f '(x[i]) pro i=1,2,..., kde f(x)= x 3 - a. Iterační vzorec je pak: x2 = x1 + (a/(x1) 2 - x1)/3 Výpočet končí, když (x2-x1) < import java.util.*; public class TretiOdmocnina { private static Scanner sc = new Scanner(System.in); public static void main (String []arg) { final double EPS = 1e-5; // 0.00001 sc.uselocale(locale.us); System.out.print("Zadej cislo: "); double zadanecislo = sc.nextdouble(); double x1, x2 = zadanecislo; do { x1 = x2; x2 = x1 + (zadanecislo/(math.pow(x1,2)) - x1)/3; while (Math.abs(x2-x1)>EPS); System.out.println("Spocteno(" + zadanecislo + ") = " + x2); System.out.println ("Java-fce(" + zadanecislo + ") = " + Math.cbrt(zadaneCislo)); Zadej cislo: 27 Spocteno(27.0) = 3.0 Java-fce(27.0) = 3.0 Strana 26 (celkem 32)
Příkazy break a continue int suma = 0; int cislo = 2; do { cislo ++; suma += cislo; System.out.print("cislo = " + cislo); System.out.println(", suma = " + suma); // break predcasne ukonceni cyklu // pokracuje se vypisem na poslední radce if (suma >= 6) { break; while (cislo < 5); konec: 4, 7 System.out.println("konec: " + cislo + ", " + suma); cislo = 3, suma = 3 cislo = 4, suma = 7 int suma = 0; // continue predcasne ukonceni iterace // a pokracovani nasledujici iteraci int cislo = 0; do { cislo++; System.out.print(" cislo = " + cislo); if (cislo == 2) { continue; suma += cislo; // uz se neprovedou a prechod na do System.out.println(", suma = " + suma); while (cislo < 4); System.out.println("konec: " + cislo + ", " + suma); cislo = 1, suma = 1 cislo = 2 cislo = 3, suma = 4 cislo = 4, suma = 8 konec: 4, 8 Strana 27 (celkem 32)
Jak na problém z úvodu přednášky? použijeme znalosti z přednášek (minulé a dnešní) problém rozdělíme na podproblémy Je dán počet testovaných případů t (1 t 100) a pro každý takový případ je na samostatném řádku zadáno celé číslo n (-1000 n 1000). Pro zadané n spočtěte a na samostatném řádku vypište výsledek následujícího úkolu: Vynásobte číslo n 567-mi, poté vydělte výsledek 9, přičtěte 7492, pak vynásobte 235, výsledek vydělte 47 a odečtěte 498. Začátek čti n v n * 567 / 9 v (v + 7492) * 235 načti n v n * 567 / 9 v (v + 7492) * 235 v v/ 47 498 vypiš v v v/ 47-498 vypiš v Konec int n = sc.nextint(); int v = n * 567 / 9; v = v + 7492) * 235; v = v / 47 498; System.out.println(v); Jaká číslice je ve vypočtené hodnotě na řádu desítek? Strana 28 (celkem 32)
Vydělíme a použijeme operaci modulo např. (123/10) % 10 = 2 Začátek čti n v n * 567 / 9 v (v + 7492) * 235 načti n v n * 567 / 9 v (v + 7492) * 235 v v/ 47 498 v v/10 mod 10 vypiš v v v/ 47-498 v v/ 10 mod 10 vypiš v Konec int n = sc.nextint(); int v = (n * 567 / 9 + 7492) * 235 / 47 498; v = v/10 % 10; System.out.println(v); Je to ale ok? n = 200 n = 50 n = -50 n = -500 6 ok 1 ok 1 ok -3??? není ok! Strana 29 (celkem 32)
Co je tedy ještě třeba? - udělat absolutní hodnotu z výsledku Začátek čti n v n * 567 / 9 v (v + 7492) * 235 v v/ 47-498 načti n v n * 567 / 9 v (v + 7492) * 235 v v/ 47 498 v v/10 mod 10 v v vypiš v v v/ 10 mod 10 v v vypiš v Konec int n = sc.nextint(); int v = (n * 567 / 9 + 7492) * 235 / 47 498; v = v/10 % 10; v = Math.abs(v); System.out.println(v); n = -500 3 ok!!! Strana 30 (celkem 32)
Co nám ještě chybí? - cyklus pro jednotlivé testované případy Začátek čti t ne t >0 ano čti n v n * 567 / 9 v (v + 7492) * 235 v v/ 47-498 v v/10 mod 10 opakuj t-krát načti n v n * 567 / 9 v (v + 7492) * 235 v v/ 47 498 v v /10 %10 v v vypiš v vypiš v Konec t t -1 Strana 31 (celkem 32)
int t = sc.nextint(); for (int i = 0; i<t; i++) { int n = sc.nextint(); int v = (n * 567 / 9 + 7492) * 235 / 47 498; v = Math.abs(v/10 %10); System.out.println(v); // t pocet testovanych pripadu Nyní už můžete samostatně doplnit zbytek programu a prakticky ověřit. KDE? Řešení je možno automaticky validovat na: http://uva.onlinejudge.org/ Co je nutno udělat? - registrace - přečíst zadání (11547 Automatic Response) - napsat celý zdrojový kód - odevzdat zdrojový kód - třída (i zdrojový soubor) musí mít jméno Main! - kontrola validace, obdržíte i validační e-mail Strana 32 (celkem 32)