Štruktúra programu

Program sa skladá zo štyroch súborov. Každý z nich využíva ako unity súbory napísané nad ním:

  • Globals.pas
    Unit starajúci sa o globálne štruktúry a premenné a o výpis chýb.
  • PolyMath.pas
    Unit obsahujúci funkcie na základné operácie s polynómami (sčítanie, násobenie, vyčíslenie...).
  • FindRoot.pas
    Unit s algoritmami na hľadanie koreňov polynómov. Definuje globálnu štruktúru Korene.
  • Zapoctak.pas
    Hlavný súbor programu. Obsahuje funkcie na parsovanie vstupu a vykonáva jednotlivé príkazy.

V kóde je samozrejme pred každou funkciou komentár čo robí, takže táto dokumentácia je vlastne duplikát. Napriek tomu som sa snažil, aby bola narozdiel od komentárov detailnejšia, najmä čo sa týka algoritmov a programovacích techník (napr. "prečo je potrebná premenná errout"). Aj preto je v mnohých prípadoch vhodné ju čítať spolu so samotným kódom.

Pri čítaní tejto dokumentácie predpokladám, že už verne poznáte príkazy programu a spôsob práce s chybami.


Globals.pas

MAXDEG | REGLAST | ERRREAL | Polynom | fin, fout | usingstdin, usingstdout | errout | register | Error(integer; string); | GlobalsExit; | inicializácia

Unit Globals;

Interface

const MAXDEG

Integerova konštanta určujúca maximálnu dĺžku polynómu. Znamená to, že najvyšší stupeň polynómu môže byť MAXDEG-1.

const REGLAST

Index posledného registra.

const ERRREAL

V mnohých prípadoch som potreboval nejako identifikovať, či funkcia vracajúca real neskončila chybou. Presne na to slúži táto konštanta.

type Polynom = array[-1..MAXDEG] of Real

Kľúčová štruktúra programu na uloženie polynómu. V trunc(Polynom[-1]) je uložená jeho dĺžka, čo je stupeň+1. Potom v prvkoch poľa Polynom[0]Polynom[dĺžka-1] sú uložené koeficienty polynómu a to tak, že v prvku Polynom[i] je uložený koeficient pri xi. Nemusí nutne platiť, že koeficient pri člene najvyššieho stupňa nie je 0; ale tam, kde to je nutné, polynóm normalizujem. Príklad uloženia polynómu 4x2+7x-5:

	[-1] [0] [1] [2]
	  3  -5   7   4

Maximálny stupeň polynómu je MAXDEG-1. Tým pádom by stačilo spraviť pole o 1 kratšie, ale ten prvok navyše je tam pre pohodlie programovania (napr. je jedno, či v podmienke testujem najprv koniec polynómu alebo čítam koeficient). Napriek tomu by sa tam nemalo nič zapisovať alebo očakávať nejakú konkrétnu hodnotu.

Poznámka: Pri zisťovaní dĺžky polynómu je nutné používať funkciu trunc (dolná celá časť), pretože prvky polynómu sú typu real. Preto na niektorých miestach programu pre istotu pridávam k ukladanej dĺžke 0,1.

Poznámka: Nulový polynóm P(x) = 0 je správne uložený tak, že v Polynom[-1] je uložené číslo 0, čo znamená, že polynóm má nulovú dĺžku. My totiž nechceme, aby koeficient pri najvyššom stupni bol nula, preto nemôže byť stupeň polynómu 0 (= dĺžka 1).

var fin, fout : text

Globálne premenné na prácu so vstupným súborom resp. konzolou (fin) a výstupným súborom resp. konzolou (fout).

var usingstdin, usingstdout : boolean

usingstdin je true, pokiaľ sa číta zo štandartného vstupu (z konzoly). V opačnom prípade je false a číta sa zo súboru. Podobne, usingstdout je true, pokiaľ sa zapisuje na štandartný výstup (do konzoly) a pri zápise do súboru je false. Tieto premenné sú potrebné z dvoch dôvodov. Po prvé, testovať koniec súboru nemá zmysel (a robí to blbosti) pri čítaní z konzoly; a za druhé, rozdielne sa vypisuje do konzoly a do súboru.

var errout : boolean

Má hodnotu true, pokiaľ sa nemajú vypisovať chybové hlášky. Používam to pri riešení polynómu.

var register : array[chr(ord('A')-2)..REGLAST] of Polynom

Globálne pole registrov. Použiteľné sú registre register['A']register['REGLAST'] vrátane. Sú ešte vyhradené ďalšie dva registre "pred": register[pred('A')] a register[pred(pred('A'))] na účely načítavania. (V znakoch sú ich indexy '@' a '?'.)

Procedure Error(err : integer; s : string)

Procedúra vypisujúca chybové hlášky. Prvý parameter je číslo chyby. Ak je nula alebo ak errout = true, nič sa nevypíše. V opačnom prípade sa vypíše ERR alebo WAR a číslo chyby (podľa toho, či to je chyba alebo varovanie). Je to navrhnuté tak, že chyby sú do čísla 20 (vrátane), ďalej sú varovania. Pokiaľ sa vypisuje na štandartný výstup, vypíše sa ešte popis chyby a za ním text v druhom parametri (s). To je užitočné vtedy, ak text výpisu závisí od toho, čo užívateľ zadal. (Napr. pri chybe 1.)

Procedure GlobalsExit

Procedúra má za úlohu "poupratovať" globálne premenné. V tomto prípade zavrie fin a fout (vstupný a výstupný súbor).

Implementation

inicializácia

Inicializujú sa globálne premenné popísané vyššie, najmä nulujú sa registre a otvárajú súbory.


PolyMath.pas

EvalPoly(Polynom; real) : real; | PlusPoly(Polynom; Polynom; Polynom); | MinusPoly(Polynom; Polynom; Polynom); | TimesPoly(Polynom; Poly; Polynom) : boolean; | DivPoly(Poly; Polynom; Polynom) : boolean; | ModPoly(Poly; Polynom; Polynom) : boolean; | DerivePoly(Polynom; Polynom); | DerivePolyX(Polynom; real) : real; | NormalizePoly(Polynom);

Unit PolyMath;

Interface

uses Globals;

Function EvalPoly(var p : Polynom; x: real) : real

Funkcia vráti hodnotu polynómu p v bode x.

Procedure PlusPoly(var a, b, res: Polynom)

Funkcia sčíta polynómy a a b a výsledok uloží do res. Ten istý polynóm sa môže v argumentoch opakovať.

Procedure MinusPoly(var a, b, res: Polynom)

Funkcia spočíta rozdiel polynómov a - b a výsledok uloží do res. Ten istý polynóm sa môže v argumentoch opakovať.

Function TimesPoly(var a, b, res: Polynom) : boolean

Funkcia vynásobí polynómy a a b a výsledok uloží do res. Ten istý polynóm sa môže v argumentoch opakovať. Pokiaľ nastane pretečenie polynómu (keď je výsledný polynóm väčší než MAXDEG), vygeneruje sa chyba a program vráti true. Ak chyba nenastane, vráti false. Využívam to pri ukladaní polynómu.

Function DivPoly(a: Polynom; var b: Polynom; var res: Polynom) : boolean

Do polynómu res uloží podiel a/b. V prípade, že b je nulový, vypíše chybu a vráti true. Následne skontroluje, či nie je b väčšieho stupňa ako a; ak áno, výsledok je 0. Následne delí klasickým štýlom - zistí, koľkokrát sa najvyšší stupeň b nachádza v najvyššom stupni a, uloží sa to do výsledku a od a-čka sa odčíta ten násobok b-čka. Napokon vráti false (viď priradenie). Ako argument sa môže ten istý polynóm opakovať.

Function ModPoly(var a : Polynom; b : Polynom; var res: Polynom) : boolean

Funkcia počíta zvyšok po delení a/b. Ak b je nulový polynóm, vyhlási chybu a vráti true. Algoritmus je podobný ako pri delení - zistí, koľkokrát sa najvyšší stupeň b nachádza v najvyššom stupni a a od a-čka sa odčíta ten násobok b-čka. Nakoniec narozdiel od delenia vráti v res to, čo zostalo v a-čku a vráti false. Ten istý polynóm sa môže v argumentoch opakovať.

Procedure DerivePoly(var a, res: Polynom)

Zderivuje polynóm a a výsledok uloží do res. Derivácia nulového polynómu je nulový polynóm, ináč sa zmenší stupeň a vypočítajú koeficienty derivácie. V argumentoch sa môže ten istý polynóm opakovať.

Function DerivePolyX(var a: Polynom; x: real) : real

Vráti deriváciu polynómu a v bode x.

Procedure NormalizePoly(var p : Polynom)

Zmenší stupeň polynómu tak, aby nezačínal nulou.


FindRoot.pas

Korene | SetPrecision(real); | GetPrecision : Real; | MtdBisection(Polynom; Real; Real) : Real; | MtdSecant(Polynom; Real; Real) : Real; | MtdNewton(Polynom; Real; Real) : Real; | SolvePoly(Polynom; integer; Korene); | MINPREC | precision | inicializácia

Unit FindRoot;

Interface

uses Globals;

type Korene = array[-1..MAXDEG+2] of Real

Štruktúra vracaná funkciou SolvePoly. V trunc(Korene[-1]) je uložený počet koreňov polynómu a samotné korene sú uložené v indexoch 1 až trunc(Korene[-1])-1 vrátane. Špeciálne môže mať trunc(Korene[-1]) hodnotu -1, čo znamená, že koreňov je nekonečno; t.j. príslušný polynóm bol nulový.

Na korene je vyhradených 0..MAXDEG+2 pozícii. Aký je dôvod, keď polynóm má maximálne stupeň-1 koreňov? Odpoveď je vo funkcii SolvePoly. V nej potrebujem uložiť ešte jednu hodnotu pred prvý a jednu za posledný koreň. Na to by stačil a rozsah do MAXDEG, pre istotu však nechávam rezervu.

Procedure SetPrecision(prec : real)

Nastaví presnosť výpočtu pre ostatné funkcie na prec. Pokiaľ je prec menšia než MINPREC, nastaví sa presnosť na MINPREC.

Function GetPrecision : Real

Vráti aktuálnu presnosť. Je to užitočné v prípade, ak chce funkcia zmeniť presnosť a po jej skončení vrátiť pôvodný stav. (viď napr. Solve)

Function MtdBisection(var p : Polynom; left, right : Real) : Real

Vráti koreň polynómu p v intervale [left, right). Zaručuje, že nájdený bod sa nebude líšiť od skutočného koreňa o viac než precision a taktiež hodnota v nájdenom bode od nuly. Funkcia vyžaduje, aby hodnota polynómu na jednom konci intervalu bola kladná a na druhom záporná (alebo na ľavom konci nulová), pretože potom vďaka spojitosti musí existovať koreň. Ak to tak nie je, vyhlási chybu a vráti ERRREAL.

Pokiaľ test prejde, funkcia nastaví premennú sign na 1 alebo -1 podľa toho, či je hodnota polynómu v ľavom kraji intervalu záporná a v pravom kladná alebo naopak. Vďaka tejto premennej nemusím neskôr špeciálne rozlišovať ktorý prípad nastal, len v príslušných podmienkach vynásobím správnu stranu nerovnosti týmto číslom.

Samotný algoritmus funguje nasledovne. Pokiaľ

  • je veľkosť intervalu väčšia ako dvakrát precision
  • alebo hodnota v ľavom alebo pravom konci intervalu je ďalej od nuly než precision
  • a ak sa nezacyklil (dvakrát za sebou vyšla tá istá hodnota),

tak vyráta stredný bod a zistí v ňom funkčnú hodnotu. Ak je to presne koreň tak skončí, ináč zmenší interval na polovicu tým, že v závislosti od hodnoty v tomto bode prestaví pravý alebo ľavý kraj na tento bod.

Po skončení cyklu program vráti nájdený bod.

Poznámka: Interval, v ktorom sa hľadá, je polootvorený preto, aby pri naväzujúcich intervaloch nebol nájdený viackrát ten istý koreň.

Function MtdSecant(var p : Polynom; left, right : Real) : Real

Táto funkcia je podobná MtdBisection.

Vráti koreň polynómu p v intervale [left, right). Zaručuje, že hodnota v nájdenom bode sa nebude líšiť od nuly o viac než precision. Funkcia vyžaduje, aby hodnota polynómu na jednom konci intervalu bola kladná a na druhom záporná (alebo na ľavom konci nulová), pretože potom vďaka spojitosti musí existovať koreň. Ak to tak nie je, vyhlási chybu a vráti ERRREAL.

Pokiaľ test prejde, funkcia nastaví premennú sign na 1 alebo -1 podľa toho, či je hodnota polynómu v ľavom kraji intervalu záporná a v pravom kladná alebo naopak. Vďaka tejto premennej nemusím neskôr špeciálne rozlišovať ktorý prípad nastal, len v príslušných podmienkach vynásobím správnu stranu nerovnosti týmto číslom.

Samotný algoritmus funguje nasledovne. Pokiaľ

  • hodnota v ľavom alebo pravom konci intervalu je ďalej od nuly než precision
  • a ak sa nezacyklil (dvakrát za sebou vyšla tá istá hodnota),

tak vyráta bod niekde v intervale a zistí v ňom funkčnú hodnotu. Ak je to presne koreň tak skončí, ináč zmenší interval tým, že v závislosti od hodnoty v tomto bode prestaví pravý alebo ľavý kraj na tento bod.

Ten "bod niekde v intervale" hľadá nasledovne. Vie, že v bode left je hodnota lval a v bode right rval. Tak odhadne polynóm lineárnou funkciou f(x) = ax+b tak, že f(left) = lval a f(right) = rval. Následne vypočíta, kde táto funkcia pretína x-ovú os a to bude hľadaný bod.

Po skončení cyklu program vráti nájdený bod.

Poznámka: Interval, v ktorom sa hľadá, je polootvorený preto, aby pri naväzujúcich intervaloch nebol nájdený viackrát ten istý koreň.

Function MtdNewton(var p : Polynom; left, right : Real) : Real

Vráti koreň polynómu p v intervale [left, right). Zaručuje, že hodnota v nájdenom bode sa nebude líšiť od nuly o viac než precision. Funkcia vyžaduje, aby hodnota polynómu na jednom konci intervalu bola kladná a na druhom záporná (alebo na ľavom konci nulová), pretože potom vďaka spojitosti musí existovať koreň. Ak to tak nie je, vyhlási chybu a vráti ERRREAL.

Pokiaľ test prejde, funkcia nastaví premennú sign na 1 alebo -1 podľa toho, či je hodnota polynómu v ľavom kraji intervalu záporná a v pravom kladná alebo naopak. Vďaka tejto premennej nemusím neskôr špeciálne rozlišovať ktorý prípad nastal, len v príslušných podmienkach vynásobím správnu stranu nerovnosti týmto číslom.

Samotný algoritmus funguje nasledovne. Ako počiatočný bod zvolí stred intervalu. Potom kým

  • je hodnota ďalej od nuly než precision
  • a ak sa nie je zacyklený (dvakrát za sebou nevyšla tá istá hodnota),

zderivuje polynóm v aktuálnom bode. Ak derivácia vyšla nula, vypíše varovanie a predá úlohu funkcii MtdSecant s tým, že oreže interval podľa poslednej nájdenej hodnoty. Potom z derivácie vypočíta, kde dotyčnica v aktuálnom bode pretína x-ovú os. Ak priesečník vyjde mimo počiatočného intervalu, rovnakým spôsobom predá úlohu MtdSecant. Ináč je nájdený bod nový bod iterácie.

Stojí za zmienku porozmýšľať nad tým, kedy cyklus skončí kvôli tomu, že sa zacyklil, t.j. kedy oldx = x. To ľahko zistíme z priradenia x := x - xval/der. Aby sa x nezmenilo, musí zrejme platiť xval/der = 0, čo môže platiť v dvoch prípadoch. Prvý je, že xval = 0, čo je dobre, pretože ak je hodnota v x nula, chceme skončiť. Druhý prípad je, keď der (derivácia) v danom bode je absolútne veľmi veľká a počítač vďaka zaokrúhľovaniu vyhodnotí výraz ako nulu. Vtedy nemôžme urobiť nič lepšie než skončiť, pretože koreň je tak blízko tomuto bodu (hoci xval je väčšie než precision), že presnosť počítača na to nestačí.

Poznámka: Interval, v ktorom sa hľadá, je polootvorený preto, aby pri naväzujúcich intervaloch nebol nájdený viackrát ten istý koreň.

Procedure SolvePoly(var p : Polynom; mtd : integer; var kor : Korene)

Nájde podľa možností všetky korene polynómu p používajúc metódu mtd a uloží ich do štruktúry kor, pričom 0 je metóda polením, 1 je sečnicová metóda a 2 je Newtonova metóda. Pritom zaručuje, že korene sú uložené vo vzostupnom poradí.

Vnútorne funguje nasledovne. Najprv si zistí stupeň polynómu a ak je -1 (nulový polynóm), 0 (konštanta), 1 (lineárna funkcia) alebo 2 (kvadratický), vypočíta korene podľa vzorca resp. uloží príslušné hodnoty do kor a skončí.

Ináč nájde extrémy polynómu, čo sú korene derivácie. Tým sú určené intervaly, kde je polynóm monotónny, teda v každom z týchto intervalov môže byť maximálne jeden koreň. Ďalšie dva korene však ešte môžu byť jeden pred prvým a druhý za posledným extrémom. Preto program nájde také body "vľavo" a "vpravo", odkiaľ bude polynóm zaručene kladný/záporný a uloží ich do poľa s extrémami.

Potom už len stačí nájsť zvolenou metódou koreň na všetkých nájdených intervaloch. Môže sa stať, že v danom intervale koreň nie je, preto jednak treba korene počítať a tiež vypnúť chybové výpisy nastavením premenej errout.

Poznámka: Body "vľavo" a "vpravo" od extrémov hľadám pomocou vlastnosti, že najvyššia mocnina v polynóme určite raz prevýši absolútny súčet všetkých ostatných. Preto stačí položiť za x absolútne maximálny koeficient, upraviť vzhľadom na koeficient pri najvyššej mocnine a vynásobiť počtom členov (čiže stupňom). Totiž ak x = am (maximálny koeficient, n je stupeň), tak xn = amn >= aiami = aixi, z čoho vyplýva n.xn >= an-1xn-1 + an-2xn-2 + ... + a0. V skutočnosti používam slabší odhad, a síce dosadzujem n.am (čo potom spôsobí násobenie nn) a ešte prirátavam jednotku. Nakoniec ešte musím ošetriť prípad, keď an < 0, kedy x vydelím priamo an.

Implementation

uses PolyMath;

const MINPREC

Minimálna dovolená presnosť. Konštantu používa funkcia SetPrecision.

var precision : Real

Presnosť výpočtov pri hľadaní koreňa. Čím je číslo menšie, tým je výpočet presnejší.

inicializácia

Nastaví východziu presnosť.


Zapoctak.pas

line | linepos | Exist(string) : boolean; | RegOut(char; integer); | ExtractArg(string); | IsNum(char) : boolean; | ReadReal : real; | ReadPoly(char) : char; | Priradenie(char); | RegManager(char); | Root; | Solve; | InputHandler : boolean; | main

Program PolynomSolver;

uses Globals, PolyMath, FindRoot;

var line : string

Globálna premenná uchovavajúca práve spracúvaný riadok zo vstupu. Premenná linepos určuje aktuálnu pozíciu kurzora v ňom.

var linepos : integer

Globálna premenná, ktorá si pamätá aktuálnu pozíciu kurzoru v line, čiže miesto, pokiaľ je vstupný riadok spracovaný. Funkcie spracuvávajúce vstup zanechávajú kurzor tak, aby line[linepos] bol prvý nenačítaný znak.

function Exist(FN : String) : boolean

Vráti true, pokiaľ súbor s názvom FN existuje.

Procedure RegOut(c: char; prec: integer)

Vypíše polynóm v registri c s presnosťou na prec desatinných miest.

Poznámka: Pôvodne mala byť dvojka v x2 vypísana v exponente, ale kvôli problémom s kódovaním to je x2.

Procedure ExtractArg(var arg: string)

Do arg uloží prvú nemedzerovú postupnosť za kurzorom (z line). Najprv prečíta všetky medzery a potom kým nie je ďalšia medzera, načítava znaky do arg. Pokiaľ nič neprečítal (napr. ak už bol koniec riadku), tak arg vráti prázdny.

Function IsNum(c: char) : boolean

Vráti true, pokiaľ je c číslica.

Function ReadReal : real

Funkcia načíta reálne číslo z line a vráti ho. Pokiaľ nejde načítať, vráti ERRREAL. Požadovaný formát čísla vyplýva zo spôsobu načítavania.

Najprv prečíta všetky počiatočné nečíselné znaky a ak narazí na koniec súboru, vráti ERRREAL. Následne skontroluje, či predošlý znak nebol '-' a ak áno, zapamätá si to a na konci vynásobi výsledok -1. Ďalej číta čísla a postupne ich pomocou mocnín 10 ukladá do premennej ret. Keď ich dočíta, pozrie, či ďalší znak nie je desatinná bodka '.'. Ak je, podobným spôsobom načíta desatinnú časť. Nakoniec vráti prečítanú hodnotu.

Function ReadPoly(memreg: char) : char

Načíta polynóm z line. Pokiaľ je zadaný ručne, uloží ho do registra memreg a vráti memreg, ináč musí byť zadaný odkazom na iný register a v tom prípade vráti index toho registra. Ak sa mu polynóm nepodarí načítať, vráti chr(1).

Najprv funkcia prečíta počiatočné medzery. Ak je ďalší znak veľké písmeno od 'A' do REGLAST, je to identifikátor iného registra a funkcia vráti jeho index. Ináč polynóm musí byť zadaný "ručne". Vtedy funkcia prečíta ľavú zátvorku a číta a ukladá reálne čísla, pokiaľ nie je buď koniec riadku, nenarazí na pravú zátvorku alebo zadaný polynóm nie je príliš veľkého stupňa. Pokiaľ niečo zlyhalo vyhlási buď chybu 3 alebo chybu 5. Nakoniec polynóm obráti, pretože je zadávaný v opačnom poradí ako je ukladaný a zmaže počiatočné nuly (NormalizePoly).

Procedure Priradenie(reg: char)

Funkcia spracuváva príkazy = a := zo vstupu. V čase spustenia funkcie je už načítaný register reg, do ktorého sa zapisuje, a tiež aj znak priradenia (=/:=). Na pravej strane sa má vyskytovať register alebo ručne zadaný polynóm, tak ho načíta pomocou ReadPoly do registra s indexom "'A'-1", ktorý je na to vyhradený (prípadne nenačíta ak bol zadaný cez register). Následne načíta operátor medzi polynómami. Ak žiaden nie je, je to obyčajné priradenie a registre prosto skopíruje. Ak je operátor "'", čiže derivácia, polynóm zderivuje do zadaného registra. V ostatných prípadoch načíta operátor ('+', '-', '*', '/', '%') a tiež polynóm na druhej strane (ak je zadaný ručne, uloží ho do vyhradeného registra "'A'-2"). Prevedie s nimi danú operáciu a ošetrí prípadné chyby. Nakoniec polynóm normalizuje a vypíše.

Procedure RegManager(reg : char)

Je to rozcestník pre príkazy, ktoré manipulujú s registrami. To sú také, ktoré začínajú písmenom registra (napr. A = ..., A (4.1)).

Procedúra načíta ďalší argument z riadku. Ak žiaden nie je, polynóm vypíše; prípadne ešte načíta presnosť. Ak je argument '=' alebo ':=', spustí Priradenie. Pokiaľ argument začína '(', môže ísť o vyčíslenie polynómu. Tak nastaví kurzor na zátvorku a skúsi načítať reálne číslo a pravú zátvorku. Ak sa to podarí, polynóm vyčísli a vypíše s najväčšou presnosťou. V ostatných prípadoch vyhlási chybu 1 a vypíše nerozpoznaný argument.

Procedure Root

Spracuváva príkazy root resp. koren na nájdenie koreňa v zadanom intervale.

Najprv načíta polynóm a interval. Na načítanie intervalu nie je špeciálna funkcia, takže to robí nasledovne. Najprv prečíta nadbytočné medzery a načíta ľavú zátvorku. Potom prečíta dve reálne čísla, zbaví sa medzier a nakoniec pravú zátvorku. Pokiaľ to niekde zlyhalo alebo je pravý koniec intervalu menší než ľavý, vyhlási chybu 8 a skončí.

Po intervale môžu nasledovať dva nepovinné parametre. Najskôr skúsi pomocou ExtractArg načítať metódu. Ak to nejde, použije Newtonovu a nastaví kurzor naspäť. Potom pomocou ReadReal skúsi načítať presnosť výpočtu. Ak to nejde, použije presnosť 10-10.

Nakoniec už len vypíše používanú metódu (ak sa nevypisuje do súboru) a použije ju. Ak nevznikla chyba, vypíše nájdený koreň. Posledný príkaz nastaví znova pôvodnú presnosť.

Procedure Solve

Spracuváva príkazy solve resp. vyries na nájdenie koreňov zadaného polynómu.

Ako prvé funkcia načíta polynóm. Potom rovnakým spôsobom ako pri procedúre Root skontroluje, či nie sú uvedené nepovinné parametre na zvolenie metódy a presnosti výpočtu a uloží ich. Ak nie sú uvedené, použije rovnaké východzie hodnoty ako v prípade Root.

Následne v prípade vypisovania na konzolu oznámi používanú metódu. Polynóm normalizuje, pretože je to nutné v zápätí pre použitie funkcie SolvePoly. Napokon v závislosti od počtu koreňov ich vypíše.

Poznámka: Normalizovanie polynómu by nemalo byť nutné, pretože všetky volané funkcie meniace polynóm ho normalizujú. Ale je dobrým zvykom, aby sa funkcia nespoliehala na ostatné funkcie a "upratala si na vlastnom piesočku".

Function InputHandler : boolean

Funkcia "programovej slučky". Jedno spustenie funkcie spracuje jeden riadok vstupu, t.j. rozpozná príkazy a vykoná ich (resp. predá ich vykonanie iným funkciám). V prípade, že načíta príkaz "ukonči program", vráti false.

Na začiatku funkcia načíta do line vstupný riadok a pomocou ExtractArg načíta príkaz. Potom nasleduje dlhá konštrukcia if - else if - else if ... rozpoznávajúca jednotlivé príkazy a predávajúca ich vykonanie ďalej.

Predsa len niektoré jednoduché príkazy spracúva funkcia sama. Sú to ukončenie programu, prázdny príkaz s komentárom a presmerovanie vstupu a výstupu. Pri posledných dvoch musí dbať na správne nastavenie globálnych premenných usingstdin a usingstdout.

Pokiaľ príkaz nerozozná, vypíše chybu 1.

main - zavádzacia funkcia

Funkcia vypíše správu o zapnutí programu a spustí programovú slučku. Keď skončí, spustí GlobalsExit na zatvorenie premenných z unitu Globals a vypíše informáciu o úspešnom ukončení programu.

Globals.pas

PolyMath.pas

FindRoot.pas

Zapoctak.pas