Dokumetace k projektu pro předměty IZP a IUS Iterační výpočty projekt č. 2 19. listopadu 2011 Autor: Vojtěch Přikryl, xprikr28@stud.fit.vutbr.cz Fakulta informačních Technologií Vysoké Učení Technické v Brně
Obsah 1 Úvod 3 2 Analýza problému a princip jeho řešení 4 2.1 Funkce počítající arcsin(x)....................... 4 2.1.1 Definice funkce......................... 4 2.1.2 Taylorův rozvoj......................... 4 2.2 Funkce počítající log a(x)....................... 5 2.2.1 Definice funkce......................... 5 2.2.2 Heuristika a převod mezi základy............... 5 2.2.3 Taylorův rozvoj......................... 6 2.3 Funkce počítající lomené čáry s chybou................ 6 2.3.1 Obecná pozorování....................... 6 3 Návrh řešení problému 7 3.1 Funkce počítající arcsin(x)....................... 7 3.2 Funkce počítající log a(x)....................... 7 3.3 Funkce počítající lomené čáry s chybou................ 8 3.3.1 Výpočet minima........................ 8 3.3.2 Výpočet maxima........................ 8 3.4 Specifikace testů............................. 9 4 Popis řešení 11 4.1 Ovládání programu........................... 11 4.2 Implementace.............................. 11 5 Závěr 13 A Použitá literatura 14 B Metriky kódu 15 2
1. Úvod Tato dokumentace se týká druhého projektu do předmětů IZP a IUS 1 vyučovaných na VUT v Brně, Fakultě informačních technologií. Zpracovaný program řeší několik problémů - výpočet funkcí arkus sinus a logaritmus o libovolném základu, obojí s předem určenou přesností a bez použití funkcí z knihovny math.h. Dále výpočet délky lomené čáry podle zadaných souřadnic v Euklidově rovině ve dvou variantách. U první varianty se výpočet týká přesně určených bodů, ve druhé variantě s chybou jsou zadané body zatíženy absolutní chybou ve směru obou os x a y. Bod pak může ležet kdekoliv ve čtverci, který je touto chybou určen a úkolem je vypočítat maximální a minimální celkovou délku. Lze si všimnout, že první varianta je pouze speciálním případem druhé varianty s absolutní chybou rovnou nule (a s důsledkem, že minima a maxima jsou si rovny), proto budu rozebírat pouze obecnou variantu s chybou. Jelikož se jedná o tři samostatné problémy (podprogramy), bude každému z nich věnována samostatná podkapitola. Rozeberu zde nejprve analýzu všech problémů, dále návrh jejich řešení a nakonec popis samotného řešení. Program byl napsán v jazyce C a jeho rozhraní je textová konzole. Prováděný podprogram uživatel zvolí při spouštění pomocí parametrů. Více o tomto v kapitole 4.1. 1 IZP = Základy programování, IUS = Úvod do softwarového inženýrství 3
2. Analýza problému a princip jeho řešení V této kapitole se podrobněji podívám na analýzu jednotlivých problémů z hlediska matematiky a pokusím se vypozorovat výhodné vztahy pro použití v programu. 2.1 Funkce počítající arcsin(x) 2.1.1 Definice funkce Funkce arkus sinus je inverzní funkcí ke goniometrické funkci sinus. Jelikož ale funkce sinus není prostá 1, tak se arkus sinus omezuje na definiční obor D = 1, 1. Pozorování: Pokud na vstupu bude zadáno číslo mimo definiční obor D, nemusím nic počítat a vrátím hodnotu NAN 2. Pozorování: Funkce je lichá 3, můžeme tedy počítat pouze v nezáporné části oboru a pro záporný vstup výsledek pouze vynásobit konstantou 1. 2.1.2 Taylorův rozvoj Iterační výpočet je vhodné počítat podle tzv. Taylorova polynomu, který dokáže v okolí zvoleného bodu aproximovat jakoukoliv funkci. Tato funkce je ve tvaru polynomu - lze ji tedy spočítat pouze s využitím základních matematických operací +,,, /, popřípadě operací z nich odvozených (mocnina, faktoriál,...). Přímo pro arkus sinus existuje Taylorův rozvoj pro okolí bodu x = 0: arcsin x = x + 1 x 3 2 3 + 1 3 x 5 2 4 5 + 1 3 5 2 4 6 x 7 7 +... pro x ( 1, 1), 1 Funkci f na definičním oboru D označujeme jako prostou na D, pokud pro každé dvě hodnoty x 1 x 2 z D platí f(x 1 ) f(x 2 ). 2 NAN = makro z knihovny math.h, znamená Not A Number (=není číslem) 3 Funkce f(x) je lichá funkce, pokud pro všechna x, pro která je f(x) definováno, je definováno i f(-x) a platí f( x) = f(x). 4
ale tento rozvoj je pro x blížící se krajům intervalu velice nepřesný. Proto jsem se rozhodl k výpočtu použít ekvivalentní převod na arkus tangens a využít vlastnosti této funkce. Převést tyto dvě funkce mezi sebou lze podle tohto vzorce: x arcsin x = 2arctan 1 + 1 x. 2 Dále jsem využil vzorce pro zmenšení argumentu funkce arkus tangens: x arctan x = 2arctan 1 + 1 + x 2 a upravil tak argument do příhodnějšího intevalu pro výpočet Taylorovým polynomem pro arkus tangens, který vypadá následovně: arctan x = x x3 3 + x5 5 x7 +... pro x 1, 1, 7 2.2 Funkce počítající log a(x) 2.2.1 Definice funkce Funkce log a (x) je inverzní funcí k funkci exponenciální a x. Platí mezi nimi ekvivalence: log a (x) = y a y = x. Obor hodnot exponenciální funkce je H = (0, ) a díky inverzi tedy bude tento obor definičním oborem D funkce logaritmické. Pro základ logaritmu a platí podmínky a (0, ) {1}, přičemž pro a (0, 1) je logaritmus klesající, a pro a (1, ) je rostoucí. Pozorování: Pokud na vstupu bude zadáno číslo mimo definiční obor D, nemusím nic počítat a vrátím hodnotu NAN. Jediná výjimka je pro hodnotu x = 0, ve které je realizována asympota a hodnota se blíží limitně mínus (resp. plus) nekonečnu pro rostoucí (resp. klesající) logaritmus. 2.2.2 Heuristika a převod mezi základy Pro správný a přesný výpočet bylo potřeba udělat heuristiku. To znamená úpravit argument funkce do výhodného intervalu, pro který jsou výsledky počítané iterační metodou co nejpřesnější. Toho mohu dosáhnout díky následujícím vzorcům: logx m = m logx log(x y) = log(x) + log(y) ( ) x logl = log(x) log(y) y 5
Heuristiku jsem se rozhodl dělat pro binární logaritmus (tzn. o základu 2), jelikož to je pro procesor velice šetrné (posun bitů je primitivní operace oproti dělení obecným číslem) a také to je pro pozdější implementaci příjemné (není nutno se starat o to, jestli je logaritmus rostoucí, nebo klesající,...). Pro následný převod mezi základy využiji velice jednoduchého vztahu: 2.2.3 Taylorův rozvoj log a (x) = log b(x) log b (a). I pro výpočet logaritmu využijeme Taylorova polynomu, který jsem krátce popsal na začátku kapitoly 2.1.2. Jak jsem již naznačil v předchozí podkapitole, budu počítat logaritmus pouze pro jeden základ, nejvhodnější je pro to přirozený logaritmus 4 značený ln x. Existuje mnoho způsobů, jak jej vyjádřit pomocí Taylorova polynomu, já jsem si vybral tento způsob: ln(x) = ln ( 1 + y 1 y ) = 2 ( y 1 + y3 3 + y5 5 + y7 7 + y9 9 + 2.3 Funkce počítající lomené čáry s chybou ), kde y = ( ) x 1, x > 0 x + 1 Vstupní posloupnost pro tento problém je interpretována jako posloupnost dvojic souřadnic v Euklidově rovině: x 1 y 1 x 2 y 2 x 3 y 3 x 4 y 4 x 5 y 5... Tyto souřadnice jsou ovšem zatíženy chybou stejnou ve směru osy x i y. Nyní tedy můžeme pro dva zadané body naleznout nekonečně mnoho různých úseček, které je spojují (jelikož bod v podstatě vnímáme rozostřeně jako čtverec) a úkolem je nalézt minimum a maximum každých dvou po sobě zadaných bodů a vypisovat aktuální součet celé lomené čáry. 2.3.1 Obecná pozorování Při analýze tohoto problému si lze všimnout, že hledané úsečky mezi 2 dílčími body budou mít vždy krajní body ležící na stranách pomyslného čtverce okolo bodu. Dále je výhodné počítat nezávisle na sobě ve směru osy x a y. Určím rozdíly x 0 a y 0 a výslednou délku d úsečky vypočítám pomocí Pythagorovy věty: d = x 2 0 + y0 2 Postup jak nalézt x 0 a y 0 popíši v kapitole 3.3. 4 přirozený logaritmus je logaritmus o základu e, což je Eulerova konstanta 6
3. Návrh řešení problému 3.1 Funkce počítající arcsin(x) Při řešení použiji vztahy a pozorování z kapitoly 2.1. Zejména odfiltruji hodnoty mimo definiční obor a využiji lichosti funkce pro počítání v nezáporné části definičního oboru. Dále si připravím argument pro iterační výpočet Taylorovým polynomem. Toho dosáhnu cyklickou aplikací vzorce x arctan x = 2arctan 1 + 1 + x 2 dokud x nebude ležet v intervalu (0, 0.1. Zároveň si značím, kolikrát pak mám celkový výsledek vynásobit aby byla provedená úprava v celkovém důsledku ekvivalentní. Pro výpočet absolutní přesnosti využiji znalost oboru hodnot, který je < π 2 ; π 2 >. Z tohoto důvodu mohu určit absolutní přesnost eps ze zadaného počtu platných cifer SIGDIG vztahem eps = 0.1 SIGDIG. Taylorův polynom se pak zpřesňuje do té doby, než absolutní hodnota rozdílu dvou po sobě jdoucích výsledku je menší než eps. 3.2 Funkce počítající log a(x) Nejprve pohlídám speciální případy, např. hodnoty mimo definiční obor, x = 0, x = 1, a = 1 a ukončím funkci s vrácením příslušných hodnot. Dále s využitím pozorování a vztahů z kapitoly 2.2 upravím argument i základ logaritmu na interval (0.2, 2). Vypočítám tedy nejdříve celou část výsledného logaritmu a Taylorovou řadou pak pouze desitinnou. Z tohoto důvodu mohu určit absolutní přesnost eps ze zadaného počtu platných cifer SIGDIG vztahem eps = 0.1 SIGDIG. Zvolený Taylorův polynom pak iteruje do té doby, než absolutní hodnota rozdílu dvou po sobě jdoucích výsledku je menší než eps. Na konec provedu převedení na správný základ a vrátím výsledek. 7
3.3 Funkce počítající lomené čáry s chybou Velikost chyby označíme v následujícím popisu jako ERR. 3.3.1 Výpočet minima Pro výpočet minimální vzdálenosti je nejdůležitější si uvědomit, že délka i pro dva neidentické body může být nulová. Stane se to, pokud se čtverce překrývají, např. pro A = [1, 1], B = [3, 3], ERR = 1. Potom bude průnikem obou čtverců bod o souřadnicích [2, 2]. Samozřejmě dva čtverce mohou mít jako průnik i úsečku nebo pravoúhelník, ale i v těchto případech je minimální vzdálenost nulová, zápornou zde nebereme v úvahu. Pro samotný výpočet tedy nejdříve analyzuji, v jakém postavení jsou zadané body. Nejdříve si je umístím podle osy x tak, aby x 1 x 2 (BÚNO1 ). Nyní rozhodnu, zda mají čtverce průnik v průmětu na osu x. Pokud platí nerovnost (x 1 + ERR) (x 2 ERR) tak tento průnik existuje a x 0 je tedy rovno nule. V opačném případě pak platí: x 0 = (x 2 ERR) (x 1 + ERR). Pro osu y pak výpočet provedu zcela analogicky. Dále dosadím do vztahu d = x 2 0 + y 2 0 z kapitoly 2.3.1 3.3.2 Výpočet maxima Pro výpočet maximální vzdálenosti je třeba si uvědomit, že délka nemůže být nikdy nulová. Např. i pro dva identické body A = [1, 1], B = [1, 1], ERR = 1. je vzdálenost nenulová, protože jako vzdálenost můžeme vzít protilehlé body čtverce. V tomto případě je tedy délka úsečky 2 2. Pro samotný výpočet znovu nejdříve analyzuji, v jakém postavení jsou zadané body. Znovu si je umístím podle osy x tak, aby x 1 x 2 (BÚNO). Nemusím však analyzovat průnik jako u minima, ale rovnou vypočtu x 0 podle rovnosti: x 0 = (x 2 + ERR) (x 1 ERR). Analogicky provedu výpočet pro osu y. Dále dosadím do vztahu d = x 2 0 + y0 2 z kapitoly 2.3.1 1BÚNO = bez újmy na obecnosti 8
3.4 Specifikace testů V této kapitole je popis testovacích hodnot, jejichž účelem je ověřit správnost výpočtů a správnost ošetření chybných vstupů. Všechny testy arkus sinu a logaritmu jsem provedl a porovnal s knihovníma funkcema (asin(double x), log(double x)) - výsledky byly shodné. Test 1 Chybná syntaxe parametrů kontrola chyby./proj2./proj2 --chyba./proj2 --arcsin x1./proj2 --arcsin 5 5./proj2 --logax -2 1./proj2 --logax 5.2 1./proj2 --logax 5-10./proj2 --lble -2 nedostatek parametrů neznámý parametr neznámý znak příliš mnoho parametrů za parametrem arcsin záporná přesnost přesnost není celé číslo základ logaritmu je záporný záporná absolutní chyba Test 2 Správnost výpočtu pro --arcsin 10 vstup očekávaný výstup 0 0.0000000000e+000 1 1.5707963268e+000-1 -1.5707963268e+000 2 nan 1e-50 1.0000000000e-050 xprikr28 nan (+ukončení programu) Test 3 Správnost výpočtu pro --logax 10 a vstup základ a očekávaný výstup 0 2 -inf 5 2 2.3219280949 5-2 nan 1e+50 10 5.0000000000e+001 10 1e-50-2.0000000000e-002 1.02 1e300 2.8667239206e-005 9
Test 4 Správnost výpočtu pro --lbl vstup očekávaný výstup 0 0 1 0 2 0 1 1 0 10 0.0000000000e+000 1.0000000000e+000 2.0000000000e+000 3.4142135624e+000 1.2469598701e+001-2 -3 2 5 1e20 0 6 14 0 0.0000000000e+000 8.9442719100e+000 1.0000000000e+020 2.0000000000e+020 nan Test 5 Správnost výpočtu pro --lble 2 vstup očekávaný výstup 0 0 1 0 2 5 0.0000000000e+000 0.0000000000e+000 0.0000000000e+000 6.4031242374e+000 1.0000000000e+000 1.6698754378e+001-2 5 8-5 6 0.0000000000e+000 0.0000000000e+000 8.4852813742e+000 1.9798989873e+001 nan 10
4. Popis řešení 4.1 Ovládání programu Program funguje v konzolovém rozhraní, nedisponuje tedy žádným grafickým prostředím. Při spuštění s parametrem -h informuje uživatele o všech ostatních možnostech parametrů, to jsou: parametry popis -h Vytiskne nápovědu arcsin sigdig Výpočet arkus sinu, sigdig - přesnost zadaná jako počet platných cifer (přirozené číslo) logax sigdig a Výpočet logaritmu, sigdig - přesnost zadaná jako počet platných cifer (přirozené číslo), a - základ logaritmu (nezaporné reálné číslo) lbl Výpočet lomené čáry s přesně zadanými body lble Výpočet lomené čáry s chybou, ERR - absolutní chyba měření souřadnic (nezáporné reálné číslo) Po spuštění program očekává na standardním vstupu (stdin) data typu popsaného v nápovědě. Pokud je na vstupu použit jiný datový typ nebo jiné neznámé znaky, program ukončí výpočet a vypíše chybové hlášení na standardní chybový výstup (stderr). V případě úspěšného zpracování vstupních dat program průběžne vypisuje výsledky na standardní výstup (stdout). Program automaticky končí po přečtení znaku EOF 1. 4.2 Implementace Program se na začátku snaží zpracovat parametry funkcí proccessparams, která naplní pomocí přístupu přes ukazatele parametry a vrátí hodnotu, která určuje typ zvoleného podprogramu. V případě špatně zadaných parametrů nebo zadání parametrů nesprávného typu se program ukončí. V opačném případě je program rozdělěn na dva cykly, první z nich se provádí pokud je zvolen podporogram pro výpočet arkus sinu nebo logaritmu, druhý pokud je zvolen výpočet 1 EOF = End Of File - konec souboru 11
délky lomené čáry. Dále se volají jednotlivé funkce, které zodpovídají za výpočet hodnot. Jsou to funkce: funkce myarcsin mylog minlength maxlength popis Výpočet arkus sinu - tato funkce je tzv. obalovací 2 a volá se z ní funkce myarctan, která je z hlavního programu nedostupná. Výpočet logaritmu - tato funkce je tzv. obalovací a volá se z ní funkce myln, která je z hlavního programu nedostupná. Výpočet maximální hodnoty u lomené čáry s chybou Výpočet minimální hodnoty u lomené čáry s chybou 12
5. Závěr Program počítá úlohy podle všech podmínek, které byly v zadání. Je ošetřen, aby se nikdy nezacyklil - pro jakýkoliv vstup bud doběhne v relativně rychlém čase nebo ohlásí chybové hlášení a ukončí činnost. Díky tomuto může být součástí jiných programů, skriptů nebo dávkových souborů. Výpočet lomené čáry s chybou byl řešen spíše analytickým pohledem. Doporučený postup s použitím intervalové aritmetiky jsem nevyužil. Na výsledcích by to nemělo nic měnit, ale do budoucna plánuji intervalovou aritmetiku vyzkoušet a porovnat s aktuálním řešením. Program je přenositelný mezi různými operačnímy systémy - byl testován na Windows 7, Linux a FreeBSD. Při kompilaci s parametry -std=c99 -Wall -Werror -pedantic-errors -g -lm nebyla ohlášená žádná chyba ani varování. Na všech uvedených systémech také proběhly úspěšně všechny testovací hodnoty se shodným výsledkem. 13
A. Použitá literatura BARTSCH, H.: Matematické vzorce. Mladá fronta, a. s., 1996, ISBN 80-204-0607-7. HEROUT, P.: Učebnice jazyka C. KOPP, 1994, ISBN 80-85828-21-9. KOPKA, H.; DALY, P.: LATEX - Podrobný průvodce. Computer Press, 2004, ISBN 80-722-6973-9. 14
B. Metriky kódu Počet souborů: 1 soubor Počet řádků zdrojového textu: 328 řádků Velikost statických dat: 316B Velikost spustitelného souboru: 17 003B (systém Linux, 32 bitová architektura, při překladu bez ladicích informací) 15