====== Cvičení 2: Cykly a reálná aritmetika ====== ==== Opakování ==== === Celočíselné operace - práce s časem === * Napište program, který načte celé číslo udávající časový interval ve vteřinách a vypíše kolik je to dní, hodin, minut a vteřin. * Tedy pokud bude vstup ''100000'' pak vypíše: ''den 1 hodin 3 minut 46 vterin 40'' === Rozdíl dvou časových údajů === * Napište program, který vypočítá rozdíl dvou časů zadaných ve formátu: ''HH:MM:SS'' === For cykly === * Napište program, který pomocí konstrukce ''for i in range(od, do, krok):'' * vytiskne čísla 10 až 500 po deseti * vytiskne čísla -20 až -600 po dvaceti ==== Cykly ==== Základní druhy cyklů * for cyklus - procházení seznamu hodnot * while cyklus - opakuj cyklus dokud platí podmínka While cyklus * while cyklus je založen na podmínce, která se vždy na začátku cyklu testuje a pokud je splněna vykoná se zadaný blok instrukcí while podmínka: blok instrukcí * Zajímavost * Lze dokázat, že nelze sestrojit program, který by rozhodl, zda jiný program skončí či nikoliv. * Člověk může dokázat, že daný while cyklus skončí * Pokud důkaz chybí, není jisté, zda program s while cyklem skončí n = int(input()) while n > 1: if n % 2 == 0: n = n // 2 else: n = 3 * n + 1 For cyklus * for cyklus standardně prochází zadaný seznam hodnot * for cyklus je založen na proměnné, která prochází seznam hodnot a pro každou hodnotu ze seznamu provede blok instrukcí for proměnná in seznam: blok instrukcí for i in "abcd": print(i) for i in (1, 10, 2, 8): print(i) * Pro standardní procházení nějakého rozmezí: * ''range(start, cíl, krok)'', * ''range(cíl)'', kdy start je automaticky 0 a krok je nastaven na 1, * ''range(start, cíl)'', kdy krok je 1. * Lze vytvořit i for cyklus, který má dynamicky měnící se seznam hodnot, případně vrací nekonečně krát stejné/rozdílné hodnoty. V tomto případě se pak jedná spíše o while cyklus a vám doporučujeme vzhledem k přehlednosti implementovat takový program jako while cyklus. Instrukce ''break'' a ''continue'' * Uvnitř bloku instrukcí mohou být příkazy ''break'' a ''continue''. * Příkaz ''break'' znamená, že se okamžitě ukončí vykonávání bloku instrukcí a ukončí se i cyklus, který tento blok instrukcí obsahuje. * Příkaz ''continue'' znamená, že * se ukončí provádění bloku instrukcí a provede se vyhodnocení podmínky (u while cyklu) * se přejde na novou hodnotu (u for cyklu) a pokud je to možné pokračuje se v provádění bloku instrukcí. * POZOR u vnořených cyklů nemají příkazy ''break''/''continue'' vliv na vnější cyklus. for i in "abcd": if i == "c": break print(i) * Výstup: a b for i in "abcd": if i == "c": continue print(i) * Výstup: a b d ==== Úkol 1 While cykly ==== * Napište program, který udělá to samé co opakování for cyklů pomocí ''while'' cyklu: * vytiskněte čísla 10 až 500 po deseti * vytiskněte čísla -20 až -600 po dvaceti ==== Úkol 2 Break loop ==== * Napište program, který načte číslo $n$ a najde jeho nejmenšího dělitele většího než 1. * Je vhodné použít konstrukci ''break'', cyklus můžete použít ''while'' i ''for''. * Otestujte svůj program na čísle 999962000357 ==== Úkol 3 Tisk šachovnice ==== * Napište program, který vytiskne čtvercovou šachovnici ze znaků 'O' a '*' o velikosti zadané uživatelem, jako vstup Vašeho programu. * Pro tisk znaku bez konce řádky použijte následující konstrukci (//end// definuje zakončení řetězce a je standardně nastaveno na nový řádek): print('.', end="") ==== Úkol 4 Odlaďte syntaktické chyby v programu ==== * Zkopírujte si následující kód do souboru * V programu odstraňte syntaktické chyby * Program spusťte a zjistěte co dělá step = 0.1 sum = 0 for is in range(1, 11): sum += step if suma == is / 10: print("Plati", sum, "rovno", is / 10) else: print("Neplati", sum, "nerovno", is / 10) ==== Úkol 5 Výpočet třetí odmocniny přičítáním ==== * Vypočtěte třetí odmocninu kladného čísla $y$, zadaného jako vstup Vašeho programu následujícím postupem: * Přičítejte k proměnné $v$ číslo 1 dokud je třetí mocnina této proměnné menší než $y$ * Přičítejte k proměnné $v$ číslo 0.1 dokud je třetí mocnina této proměnné menší než $y$ * Přičítejte k proměnné $v$ číslo 0.01 dokud je třetí mocnina této proměnné menší než $y$ * Proměnná $v$ obsahuje odmocninu čísla $y$ s přesností na dvě desetinná čísla ==== Úkol 6 Výpočet třetí odmocniny přičítáním se zadanou přesností ==== * Upravte předchozí program tak, aby pracoval se zadanou přesností * Program načte číslo $y$ a $n$ a nalezne třetí odmocninu z čísla $y$ na $n$ desetinných míst * Upravte algoritmus, aby uměl spočítat i třetí odmocniny ze záporných čísel ==== Úkol 7 Půlení intervalu ==== * Metoda půlení intervalu hledá řešení obecné rovnice $f(x)=0$, kdy známe dva body $x_1$ a $x_2$ takové, že $f(x_1)<0$ a $f(x_2)>0$. * Algoritmus rozpůlí interval mezi body $x_1$ a $x_2$, tedy nalezne bod $x' = \frac{x_1+x_2}{2}$ a pokud je $f(x')<0$ pak nahradí bod $x_1$ bodem $x'$, jinak nahradí bod $x_2$ bodem $x'$. * Výše uvedený krok se opakuje dokud není $|x_1-x_2|<\epsilon$, kde $\epsilon$ je požadovaná přesnost. * V případě hledání třetí odmocniny z čísla //y//: * $f(x)=x^3-y$ * Pokud $f(x)=0$, tak $x^3-y=0$, což lze zapsat jako $x^3=y$ a tedy $x=\sqrt[3]{y}$ * Napište program, který nalezne třetí odmocninu zadaného čísla $y$ na 8 desetinných míst * (výpočet ukončíte pokud $|x_1-x_2|<0.000000001$). * Na počátku zvolte $x_1=0$ a $x_2=y$ pro kladná $y>1$, $x_1=y$ a $x_2=0$ pro záporná $y< -1$, a $x_1=-1$ a $x_2=1$ v ostatních případech. ==== Úkol 8 Výpočet třetí odmocniny Newtonovou metodou ==== * Newtonova (Babylónská) metoda tečen $x_{i+1}=\frac{f(x_i)}{f'(x_i)}$ pro třetí odmocninu z čísla $y$ dostáváme $$x_{i+1}=\frac{1}{3}\left( 2x_i + \frac{y}{x_i^2} \right)$$ * Řada $x_i$ konverguje k třetí odmocnině z čísla $y$ * $x_0$ můžete nastavit na libovolnou hodnotu různou od 0, např $x_0=1$, případně na lepší odhad. * Čím lepší odhad nalezneme, tím rychleji řada konverguje. * Výpočet lze ukončit * např. podle rozdílu $|x_{i+1}-x_i| < \epsilon$ * nebo lze testovat $|x_i^3 - n| < \epsilon$ ==== Úkol 9 Výpočet třetí odmocniny - porovnání ==== * Spusťte všechny úlohy 6 - 8 pro stejné hodnoty čísla $y$ a zjistěte, které řešení potřebuje nejmenší počet kroků (změna hodnoty $x$) k nalezení řešení s přesností na 8-desetinných míst $\epsilon=10^{-8}$. ===== Domácí příprava ===== Procvičte si znalosti z tohoto cvičení na následujících příkladech: * Algoritmus pro výpis čísel -100,-99,-80,-79,-60,-59, $\ldots$ -20,-19,0,1,20,21, $\ldots$, 100. * Výpis hodnot sin(x) v intervalu $<0,2\pi)$ se zadaným krokem $\delta$. Např. pro $\delta=0.1$ program vypíše sin(0), sin(0.1), sin(0.2) atd. ===== Domácí úkol ===== ==== Lehká varianta ==== * Napište program **root.py** který metodou půlení intervalu spočítá kořen zadaného polynomu 5. stupně na intervalu $< -1,1>$ * **Vstup:** je šest řádek ze standardního vstupu, každá řádka obsahuje jedno reálné číslo. Označme je postupně $a, b, c, d, e, f$. * **Výstup:** jedno číslo, které je řešením rovnice $a\cdot x^5 + b\cdot x^4 + c\cdot x^3 + d\cdot x^2 + e\cdot x + f=0$ pro $x$ v intervalu $< -1,1>$ * Pro výpočet použijte metodu půlení intervalu. * Výsledek nalezněte s přesností na 8 desetinných míst (výpočet ukončíte pokud $|x_1-x_2|<0.000000001$). * Pro prvotní nastavení krajních použijte meze intervalu $-1$ a $1$ * Použití jakékoliv knihovní funkce (např. ''math.log'') není dovoleno, program volající cizí funkce nebude hodnocen. **Příklady** Vstup: 1.0 -86.57953 2211.04584 -14290.33697 -68290.75634 36557.68411 Výstup 0.489 Polynom: $x^5 - 86.57953 \cdot x^4 + 2211.04584 \cdot x^3 - 14290.33697 \cdot x^2 - 68290.75634 \cdot x + 36557.68411$ Vstup: 0.0 1.0 -24.56866 -630.51769 2795.40059 1895.26625 Výstup -0.599 Polynom: $1. \cdot x^4 -24.56866 \cdot x^3 -630.51769 \cdot x^2 + 2795.40059 \cdot x + 1895.26625$. ==== Těžká varianta ==== * Napište program **base.py**, který od sebe odečte čísla v zadané číselné soustavě * **Vstup:** čtyř řádky standardního vstupu, první řádka definuje základ číselné soustavy, druhá, třetí a čtvrtá obsahují tři desetinná čísla v zadané číselné soustavě * **Výstup:** číslo v zadané soustavě, které je součtem prvních dvou čísel od kterých je odečteno číslo třetí nebo ''ERROR'' * Např. desetinné binární číslo $101.0101 = 1*2^2+0*2^1+1*2^0+0*2^{-1}+1*2^{-2}+0*2^{-3}+1*2^{-4} = 5.3125$. * Základ výstupní soustavy je v rozmezí 2 .. 36, správnost základu soustavy (první vstup) nemusíte testovat. * Pokud je na vstupu špatně zadané číslo (obsahuje jiné znaky než takové, které jsou přípustné pro zadanou soustavu a znak '.', případně obsahuje znak '.' vícekrát), pak program vytiskne na výstup ''ERROR'' * Pro soustavy o základu menším nebo rovno 10, obsahuje desetinné číslo pouze čísla od 0 .. základ soustavy - 1 a znak ''.'' * Pro soustavy o základu větším než 10, obsahuje desetinné číslo na výstupu čísla 0,..,9 a malá písmena 'a', .. , 'z' taková, že hodnota $ord(znak)-ord('a')< zaklad\_soustavy-10$. * **Řešení vypisujte bez tzv. leading/trailing zeros** * příklad leading zeros: "00.1" (správně má být "0.1"), "-010.1" (má být "-10.1") * příklad trailing zeros: "0.00100" (správně je "0.001"), "-0.620" (správně je "-0.62") **Příklady** Jednoduchý příklad, základ soustavy 3: Vstup: 3 1.2222 1.0121 2.12 Výstup: 0.122 Jednoduchý příklad, základ soustavy 33: Vstup: 33 pm.ttnp1 l.e12w n.m6hqnq Výstup: pk.lo8ua7 Složitější příklad, záporný výsledek, základ soustavy 2: Vstup: 2 1.10011 10.011 1101.0011 Výstup: -1001.00111 Chybné zadání, soustava 4: Vstup: 4 10.1313 11.2302214 23021.331 Výstup: ERROR