Hledání průsečíku pomocí půlení intervalu
(2016)
Metodou půlení intervalu nalezněte průsečík s osou x u funkce dané polynomem (například f=10*(x-200)3=10x3 - 6000x2 + 1200000x - 80000000) na daném intervalu (například-1000 až +1000)
(představu o průběhu funkce lze získat například pomocí online nástroje http://wolframalpha.com .
Princip metody (jedná se o „dohledání“ průsečíku v
případě, že na intervalu existuje jeden průsečík):
1) Vypočtěte
hodnoty v krajních bodech intervalu a uprostřed
2) Vypusťte tu z
hodnot na kraji, která má stejné znaménko jako prostřední hodnota.
(Předpokládáme, že existuje pouze jeden průsečík na daném
intervalu).
3) Zbylé dvě hodnoty použijte jako krajní hodnoty pro
výpočet podle bodu 1).
4) Výpočet ukončete v okamžiku, kdy hodnota
spočítaná pro prostřední bod nabyde hodnotu „nula“ (zde
musíme počítat s tím, že při „diskrétních“ výpočtech
nemusíme přesné hodnoty nula dosáhnout. Proto stanovíme určitý
interval, ve kterém budeme hodnoty považovat za nulové (v závislé
proměnné/amplitudě, osa y). Pokud bychom uvažovali, že průběh v okolí
průsečíku bude velice strmý (například 1/x v okolí nuly), museli
bychom položit i podmínku na minimální interval v nezávislé proměnné
(„čas“, osa x)).
0) Vytvořte projekt a v něm soubor mainpul.c (kde bude funkce main a volání funkcí), soubor funkcepul.c (kde budou funkce z bodů 2 a 3) a soubor funkcepul.h (zveřejňující funkce ze souboru funkcepul.c).
1) Načtěte ze vstupu koeficienty funkce třetího řádu (pro uvedenou funkci uvažujte vstup 10;-6000;1200000;-80000000 (pro uložení použijte reálný typ-pole)). Dále načtěte tři čísla pro okraje intervalu a přesnost (pro uvedenou funkci -1000;1000;0.1 (reálné typy, pole pro interval, hodnota pro přesnost))
Jelikož vstup z klávesnice je dosti rozsáhlý, byl by při testování
programu problém s neustálým zadáváním hodnot. Proto použijte pro
načítání hodnot mechanizmus přesměrování vstupu místo klávesnice ze
souboru. Vytvořte si soubor (například vstup.input s daty „
10;-6000;1200000;-80000000 -1000;1000;0.1“.
Pro
přesměrování vstupu na soubor se na příkazové řádce používá symbol
pro přesměrování „<“ program.exe <
input.stdin. Tento mechanizmus
funguje i v ladícím modu. Soubor input.stdin je
ovšem nutné umístnit do pracovního adresáře, kterým je adresář se
zdrojovými texty (standardně by tento soubor byl ve stejném adresáři
jako spustitelný soubor). Přesměrování provedeme uvedením textu
„<input.stdin“ do
parametru argumenty překladače (u projektu volba properties/
configuration properties/ debugging/command arguments).
Dojde-li k chybě při načítání koeficientů, zahlaste chybu 1 (například při zadání “ 10;-6000;1200000“). Při špatném vstupu hodnot krajů intervalu zahlaste chybu 2 (například při “9000;1000;0.1“), je-li špatně hodnota tolerance (například nepodaří-li se najít průsečík do 100 iterací. Například řetězec “-10000000;10000000;0“) zahlaste chybu 3.
2) Napište funkci, která na základě dodaných parametrů vypočte pro
dané koeficienty polynomu hodnotu v daném bodě. Pro mocninu lze
použít funkce pow. (Pozn.: lze použít i cyklus s výpočtem v těle:
cislo = cislo*aX + koef[i];.
Výpočet f(x)=k[2]*x*x+k[1]*x+k[0] ma 6 operaci; Výpočet f(x)=(k[2]*x+k[1])*x+k[0] ma 5 operaci;)
Funkce bude mít prototyp double
HodnotaFunkce(unsigned int aRad, double aKoef[], double
aX).
Správnost funkce vyzkoušejte pro vstupy s příslušnými
kontrolními výstupními hodnotami:(vstup,vystup), (0,-80000000),(1,-78805990),
(-1,-81206010)
3) Napište funkci („normální“ a následně ji zkuste
navrhnout jako rekurzivní), která vypočte průsečík s nulou. Funkce
bude mít prototyp double Prusecik (unsigned int aRad, double
aKoef[],double aOkraje[2], double aTolerance). Funkce rekurzivní
bude mít prototyp double Prusecik Rek(unsigned int aRad, double
aKoef[],double aOkraje[2], double aTolerance). Tolerance určuje v
jakém intervalu ukončit výpočet (bude-li výsledek v intervalu
+-Tolerance, prohlásíme ho za nulu a ukončíme výpočet).
Funkce
vypočte hodnoty v krajních bodech a uprostřed mezi nimi. Pokud je
hodnota uprostřed dostatečně malá (v intervalu +-Tolerance), pak
vrátí jí odpovídající polohu (hodnotu vstupu z intervalu, která dá
příslušný výsledek). Jinak pokračuje (nebo u rekurzivní formy zavolá
opět funkci Prusecik) s hodnotami krajnich bodů, kdy jeden z
původních (ten jehož hodnota má stejné znaménko jako střední) nahradí
bodem středním.
Pro špatné vstupní hodnoty mezí (například “900;1000;0.1“ kde neleží průsečík s osou x) zahlásí funkce chybu tím, že vrátí hodnotu větší než je horní mez prohledávaného intervalu (pro účely sjednocení z důvodu ladících kontrol stanovme, že vrátí hodnotu horní meze, ke které přičte jedničku).
Po dobu ladění si pro kontrolu činnosti algoritmu tiskněte hodnoty mezí. K tisku použijte makro LOG1, LOG2..., kde číslo v názvu udává počet tisknutých parametrů pomocí funkce printf. Pro toto makro použijte mechanizmus podmíněného překladu – v případě nadefinování proměnné LADENI (pomoci #define) bude makro tisknout hodnoty (tj. bude obsahovat printf), v opačném případě bude makro „prázdné“ (tj. při překladu se na jeho místo neumístí žádný text).
Pozn.: funkci LOGX lze nahradit funkcí univerzální pro libovolný počet paramterů LOG(format, …) printf(format, __VA_ARGS__). „Parametr“ tři tečky značí, že na tomto místě může být libovolný počet parametrů. Tyto parametry se umístí do místa označeného __VA_ARGS__.
4) Pomocí funkcí z bodů 2) a 3) (zavoláte funkci z bodu 3, která dále využívá funkci z bodu 2) vypočtěte průsečík zadané funkce s osou x. Vypočtenou (vrácenou) hodnotu vytiskněte.
5) Upravte program tak, aby pracoval pro libovolný řád od 1 do MAXRAD (nastavte jako konstantu pomocí #define, v programu volte hodnotu 10). Jako první tedy načtěte ze vstupu celočíselnou hodnotu – řád polynomu funkce (pro uvedenou funkci 3 (celočíselný typ)). Při hodnotě řádu mimo stanovené meze, vraťte chybový kód 4. Následně načtěte koeficienty funkce, kdy jejich počet musí odpovídat zadanému řádu.
Poslední změna 2015-02-22