2.Prednaska
2. Prednáška |
For-cyklus
Pozrite sa na program, v ktorom sme nejaký príkaz zapísali úplne rovnako viackrát:
procedure Form1.Button1Click(Sender: TObject); begin Image1.Canvas.TextOut(Random(300), Random(200), 'Hello'); Image1.Canvas.TextOut(Random(300), Random(200), 'Hello'); Image1.Canvas.TextOut(Random(300), Random(200), 'Hello'); Image1.Canvas.TextOut(Random(300), Random(200), 'Hello'); Image1.Canvas.TextOut(Random(300), Random(200), 'Hello'); end;
Vo väčšine programovacích jazykoch existujú konštrukcie (hovoríme im cyklus), pomocou ktorých sa jednoducho zapíše opakovanie nejakých príkazov. Začneme tzv. cyklom s pevným počtom opakovaní. Jeho zápis v Pascale (syntax) je:
for premenná := hodnota1 to hodnota2 do iba jeden príkaz; |
alebo
for premenná := hodnota1 to hodnota2 do begin viac príkazov; end |
Zapíšeme predchádzajúci príklad pomocou tejto konštrukcie a vysvetlíme, ako funguje:
procedure TForm1.Button1Click(Sender: TObject);
var
I: Integer;
begin
for I := 1 to 5 do
Image1.Canvas.TextOut(Random(300), Random(200), 'Hello');
end;
|
![]() |
Programová konštrukcia for-cyklus v tomto príklade označuje, že jeden príkaz (výpis textu) sa zopakuje 5-krát. For-cyklus na to používa tzv. počítadlo cyklu (niekedy sa tomu hovorí aj riadiaca premenná cyklu). Je to nejaká premenná, v ktorej si program postupne počíta prechody cyklu. Na začiatku sa do tejto premennej priradí štartová hodnota cyklu (hodnota1, t.j. 1), potom sa bude tejto premennej táto hodnota postupne zvyšovať o jedna, až kým nadobudne koncovú hodnotu cyklu (hodnota2, t.j. 5). Pre každú túto hodnotu (teda presne 5-krát) sa vykoná telo cyklu, t.j. jeden príkaz Image1.Canvas.TextOut(Random(300), Random(300), 'Hello');
Pre for-cykly platí, že koncová hodnota hodnota2 by nemala byť menšia ako štartová hodnota1, lebo inak sa telo cyklu nevykoná ani raz. Zrejme, ak sú tieto dve hodnoty rovnaké, telo cyklu sa vykoná len raz.
Ešte pripomíname, že premenná cyklu musí byť už zadeklarovaná. Táto premenná ešte pred príkazom cyklu je "obyčajnou" premennou a môžeme ju používať na ľubovoľné účely. Počas cyklu sa stáva počítadlom a nesmie sa nijakým spôsobom do nej priraďovať. Po skončení cyklu (až po záverečný end) je to opäť obyčajná premenná.
Ak chceme vo for-cykle vykonať viac ako jeden príkaz, použije zápis s konštrukciou begin a end. Ukazuje to nasledovný príklad:
Program nakreslí na náhodné pozície 9 žltých kruhov. V tomto cykle sa postupne vykonajú príkazy tela cyklu a to 9-krát. Ak si uvedomíme, že počas každého prechodu cyklu bude mať počítadlo (premenná I) príslušnú hodnotu. Teda pri prvom prechode hodnotu 1, pri druhom 2 atď. a pri poslednom hodnotu 9. Túto premennú môžeme v tele cyklu používať ale nemeniť, preto ju vypíšeme do nakreslených kruhov:
Premennú cyklu môžeme využiť aj na umiestňovanie kruhov v ploche. Do X a Y nebudeme priraďovať náhodné hodnoty, ale hodnoty vypočítame pomocou premennej I. Y bude konštantné, X vypočítame tak, aby sa kruhy nakreslili tesne vedľa seba. Napr. prvý kruh nech má X = 30, druhý kruh 50, ďalší 70 a každý ďalší o 20 viac (lebo priemer je 10 a kruh je posunutý o veľkosť dvoch priemerov). Môžeme to zapísať takýmto výrazom:
Pozrime príkazy v tele cyklu. Dva z nich sú priraďovacie príkazy a stále (9-krát) sa priraďujú tie isté hodnoty. Takéto príkazy môžeme vytiahnuť pred cyklus, lebo pre každý prechod majú mať rovnaké hodnoty. Napr.
procedure Form1.Button1Click(Sender: TObject);
var
I, X, Y: Integer;
begin
X := 30;
Y := 100;
Image1.Canvas.Brush.Color := clYellow;
for I := 1 to 9 do
begin
Image1.Canvas.Ellipse(X - 10, Y - 10, X + 10, Y + 10);
Image1.Canvas.TextOut(X - 3, Y - 8, IntToStr(I));
X := X + 20;
end;
end;
V tomto príklade nepočítame X pomocou premennej cyklu I, ale pred cyklom sme do nej priradili počiatočnú hodnotu 30 a pri konci cyklu sme túto hodnotu zvýšili o 20, takže v ďalšom prechode už bude X o 20 väčšie.
V ďalšom príklade ukážeme spôsob, ako sa niečo vypisuje do grafickej plochy, pričom by tento výpis mal ísť do viacerých riadkov.
Všimnite si použitie premennej Y, ktorej sme ešte pred cyklom priradili počiatočnú hodnotu 0 a po každom prechode cyklu sme túto premennú zvýšili o 20 (Y:=Y+20). Tiež je zaujímavá malá modifikácia %d parametra vo funkcii Format. Namiesto %d píšeme %3d alebo %5d, ktoré teraz označujú šírku vypisovanej hodnoty, t.j. počet znakov, na ktoré sa zadané číslo vypisuje. Pri tomto výpise sa číslo doplní medzerami zľava.
Niekedy budeme riešiť úlohu, ktorú vieme zapísať bez cyklu (niekedy je to dosť zdĺhavé), ale ak ju treba zapísať cyklom, môžeme mať s tým ešte problémy. Pozrite tento program, ktorý kreslí niekoľko úsečiek pod sebou:
Radi by sme riadok s kreslením úsečky Line(X1, Y1, X2, Y2) opakovali v nejakom for-cykle. Vidíme, že sa nakreslilo 9 úsečiek. Pre každú z nich sa nejako mení Y1 aj X2 aj Y2. Predpokladajme, že to budeme riešiť pomocou cyklu for I := 1 to 9 do. Vidíme, že Y1 aj Y2 je 20-násobok I. X2 sa stále zmenšuje, pričom pre I=1 je to 300, pre I=2 je to 270, pre I=3 je to 240, atď. Teda vidíme, že sa opakuje tento jeden príkaz:
Image1.Canvas.Line(50, 20 * I, 330 - 30 * I, 20 * I);
Program prepíšeme pomocou for-cyklu:
Na tomto príklade ukazujeme, že pri zápise časti programu pomocou cyklu môžeme využiť to, že niekoľko krokov rozpíšeme bez cyklu a hľadáme, čo sa v ňom opakuje a čo pritom bude treba prepočítať. Do tela cyklu sme pridali dvojicu príkazov Repaint; Sleep(500); - tieto slúžia na mierne spomalenie výpočtu a označujú: okamžite vykresli grafickú plochu a potom pozdrž beh programu o pol sekundy. Príkaz Sleep(ms) pozdrží o ms mikrosekúnd, preto 500 označuje 500/1000 = 1/2 sekundy. Tento príkaz používame len v úvodných prednáškach kvôli názornosti, neskôr sa naučíme správny spôsob spomaľovania behu, napr. pre animáciu.
Farby
Môžeme predpokladať, že všetky farby v počítači sú namiešané z troch základných farieb: červenej, zelenej a modrej (model RGB, teda Red, Green, Blue). Farba závisí od toho, ako je v nej zastúpená každá z týchto troch farieb. Zastúpenie jednotlivej farby vyjadrujeme číslom od 0 do 255 (zmestí sa do jedného bajtu), napr. žltá farba vznikne, ak namiešame 255 červenej, 255 zelenej a 0 modrej. Ak budeme zastúpenie každej farby trochu meniť, napríklad 250 červenej, 240 zelenej a hoci 100 modrej, stále to bude žltá, ale v inom odtieni. Na skladanie farieb máme k dispozícii funkciu RGBToColor, ktorej zadáme tri čísla od 0 do 255 a ona vytvorí príslušnú farbu. Napr. niektoré zo známych preddefinovaných farieb majú takéto vyjadrenie:
clBlack = RGBToColor(0, 0, 0) clRed = RGBToColor(128, 0, 0) clGreen = RGBToColor(0, 128, 0) clBlue = RGBToColor(0, 0, 255) clGray = RGBToColor(128, 128, 128) clYellow = RGBToColor(255, 255, 0) clWhite = RGBToColor(255, 255, 255)
V skutočnosti sú farby v počítači zakódované v štvorbajtovej hodnote – rovnako ako celé čísla Integer. Pascal dovoľuje pracovať s týmito farbami, ako keby to boli celé čísla. Ak predpokladáme, že rôznych farieb v počítači je 256*256*256 (čo je 16777216), tak by sme náhodnú farbu mohli generovať takýmto zápisom:
Image1.Canvas.Brush.Color := Random(256 * 256 * 256);
Toto môžeme zapísať aj pomocou funkcie RGBToColor, prípadne môžeme "namiešať" naozaj ľubovoľnú farbu podľa našich predstáv. Môžeme generovať náhodné farby s rôznymi vlastnosťami, napr.
RGBToColor(Random(255), Random(255), Random(255)) // úplne náhodná farba RGBToColor(0, 0, Random(255)) // odtiene modrej (od čiernej po modrú) RGBToColor(Random(255), 0, Random(255)) // náhodná fialová (červená až modrá)
Nasledujúci program nakreslí vedľa seba tri farebné kruhy s rôznymi odtieňmi červenej, zelenej a modrej farby. Každé zatlačenie tlačidla jemne zmení tieto odtiene.
Zaujímavý efekt dosiahneme, keď meníme farby tak, že postupne prechádza jedna farba do druhej. Napr. Začneme s maximálnou červenou, červenú postupne znižujeme a pritom zvyšujeme zelenú, na záver ostane vidieť už len zelená.
Ak do cyklu vložíme príkaz Repaint;, program sa trochu spomalí hoci sme tam ani nevložili Sleep(...);.
Podmienený príkaz
Pri programovaní často narazíme na situácie, keď potrebujeme, aby sa nejaké príkazy vykonali len pri splnenej podmienke. Prípadne neskôr uvidíme, že aj cyklus môže bežať nie pevný počet krát, ale len kým je splnená nejaká podmienka. Najjednoduchší spôsob vytvárania podmienok je použitie relačných operácií: <, <=, >, >=, <>, =. Pomocou nich môžeme porovnávať nejaké dve číselné hodnoty, napr.
X < 150 Y > Image1.Height div 2 X + Y > 200
Pri takýchto výrazoch predpokladáme, že relačné operátory majú nižšiu prioritu ako všetky aritmetické operácie. Z matematiky už poznáme aj niektoré logické operácie ako
- not - negácia podmienky
- and - musí platiť súčasne
- or - musí platiť aspoň jedna z podpodmienok
Keď zhrnieme skúsenosti z matematiky pri vyhodnocovaní aritmetických výrazov a pridáme pravidlá Pascalu pre relačné a logické operácie, dostaneme takúto tabuľku:
unárne not násobenie a delenie * / div mod and súčet a rozdiel + - or relačné = < <= > >= <>
Najvyššiu prioritu má logická negácia not. Trochu nižšiu majú násobenie, delenie a logický súčin and. Ak je v jednom výraze viac operátorov z rovnakej úrovne, tak sa väčšinou vo výraze vyhodnocujú zľava doprava. Samozrejme, že budeme využívať okrúhle zátvorky, aby sme toto poradie vyhodnocovania ovplyvnili podľa našich predstáv. Pozrime sa na zložitejší výraz:
X < 100 or Y >= 50
Podľa tabuľky priorít vidíme, že ako prvé sa bude vyhodnocovať or, t.j. 100 or Y, potom sa výsledok tejto operácie porovná, či je väčší ako X a ďalej by sa to porovnávalo s 50 ... Zrejme sme tu neočakávali, že by sa mal vyhodnocovať práve takto (Pascal by aj tak hlásili chybu, že sa to nedá vyhodnotiť). Správne to teda malo vyzerať takto:
( X < 100 ) or ( Y >= 50 )
Teraz sa naučíme tzv. príkaz vetvenia (podmienený príkaz). Jeho zápis v Pascale (syntax) je:
if podmienka then príkaz1 else príkaz2; |
Podobne ako for-cyklus, aj tento príkaz v sebe obsahuje nejaké iné príkazy a v tomto prípade sú dva: 1 a príkaz2. Vnorený príkaz príkaz1 sa vykoná jedine vtedy, keď výsledok podmienky je pravdivý inak sa vykoná len vnorený príkaz príkaz2. Teda vždy sa vykoná len jeden z týchto dvoch príkazov a to buď iba príkaz1, ak bola podmienka splnená alebo iba príkaz2, ak bola podmienka nesplnená.
Prvý program, v ktorom použijeme podmienený príkaz, po zatlačení tlačidla Button1 vygeneruje 1000 bodov X, Y na náhodných pozíciách a ak bude X menšie ako 150, nakreslí modrú bodku veľkosti 10 inak bude červená:
Pridáme ešte jednu podmienku: bodky budú žlté, ale len keď je Y > 100 a inak nech ostanú modré alebo červené. Tento zápis ale obsahuje chybu:
Problémom je použitie druhého if-príkazu. Totiž tento príkaz, ak je Y > 100 nastaví farbu pera na žltú, inak vykoná jeden príkaz za else. Lenže komentár sa nepovažuje za príkaz a preto príkazom za else je až nakreslenie bodky (pomocou Line). Preto sa žlté bodky vôbec nekreslili: v podmienenom príkaze sa buď nastavila farba (zbytočne) alebo kreslila bodka.
Uvedieme niekoľko správnych riešení, napr. v else-vetve naozaj nič nevykonáme:
if Y > 100 then Image1.Canvas.Pen.Color := clYellow else ; // nemeň farbu - nechaj ju nastavenú, ako bola
Bodkočiarka za else označuje koniec príkazu vo vetve, t.j. za slovom else je prázdny príkaz. Iný zápis:
if Y > 100 then Image1.Canvas.Pen.Color := clYellow else begin // nemeň farbu - nechaj ju nastavenú, ako bola end;
Ešte jeden dobrý zápis, v ktorom sme otočili podmienku:
if Y <= 100 then else Image1.Canvas.Pen.Color := clYellow;
Najlepšie riešenie bude použitie neúplného podmieneného príkazu, t.j. variantu príkazu, ktorý nemá else vetvu:
if podmienka then príkaz; |
Ak za príkaz v prvej vetve zapíšeme bodkočiarku, označíme, že else-vetva už nebude, ale za ním už nasleduje nejaký ďalší príkaz. Správne riešenie žltých bodiek by mohlo vyzerať takto:
V ďalšom príklade nakreslíme na náhodných pozíciách 20 štvorčekov, pričom sa budú striedavo zafarbovať žltou a zelenou farbou.
Keby namiesto I mod 2 = 1 bola napr. podmienka I mod 3 <> 0, tak sa budú striedať dva žlté štvorce a jeden zelený.
Aj samotná podmienka môže testovať nejakú náhodu, napr. nech približne 10% (každá desiata) bodiek je väčších a inak zafarbených.
Všimnite si, že sme museli použiť dvojice príkazov begin a end, nakoľko chceme aby sa aj v jednej aj v druhej vetve príkazu if vykonávalo viac príkazov.
Podmienený cyklus
Najprv program, ktorý nakreslí tesne vedľa seba 20 zväčšujúcich sa štvorcov. Veľkosti: 10, 20, 30, 40, 50, ... Keďže štvorcov má byť 20, použijeme for-cyklus, napr. takto:
Vidíme, že sa zobrazilo len 7 štvorcov. Ostatné sa kreslili zbytočne, lebo sú (aspoň čiastočne) mimo grafickej plochy. Počet týchto štvorcov závisí od šírky grafickej plochy, takže bolo by dosť náročné tento počet dopredu vypočítať, aby for-cyklus prebehol menej krát.
Väčšina programovacích jazykov má aj ďalšiu konštrukciu cyklu, tzv. cyklus s podmienkou. Takýto cyklus nemá dopredu daný počet prechodov (ako je to vo for-cykle), ale pred každým prechodom cyklu sa skontroluje dopredu daná podmienka a telo cyklu sa vykoná len keď je podmienka splnená. Zápis takéhoto cyklu v Pascale (syntax) je:
while podmienka do iba jeden príkaz; |
alebo
while podmienka do begin viac príkazov; end |
Prepíšeme predchádzajúci príklad so štvorcami použitím while-cyklu:
Vidíme, že kreslenie štvorcov sa zastavilo v správnom momente: ďalší kreslený štvorec by už presahoval okraj grafickej plochy. Pozrime sa, ako sa postupne vyhodnocoval tento program (predpokladáme, že šírka grafickej plochy je 304, ? označuje nedefinovanú hodnotu):
premenná A premenná X podmienka X + A < Image1.Width begin ? ? ? X := 10; 10 A := 10; 10 while X + A < Image1.Width True kresli štvorec Inc(X, A); 20 Inc(A, 10); 20 while X + A < Image1.Width True kresli štvorec Inc(X, A); 40 Inc(A, 10); 30 while X + A < Image1.Width True kresli štvorec Inc(X, A); 70 Inc(A, 10); 40 while X + A < Image1.Width True kresli štvorec Inc(X, A); 110 Inc(A, 10); 50 while X + A < Image1.Width True kresli štvorec Inc(X, A); 160 Inc(A, 10); 60 while X + A < Image1.Width True kresli štvorec Inc(X, A); 220 Inc(A, 10); 70 while X + A < Image1.Width True kresli štvorec Inc(X, A); 290 Inc(A, 10); 80 while X + A < Image1.Width False end;
Nasledujúci program môže byť poučný vo viacerých veciach:
var I: Integer; begin I := 37; while I > 0 do Dec(I); Image1.Canvas.Font.Height := 30; Image1.Canvas.TextOut(10, 10, IntToStr(I)); end; |
![]() |
While-cyklus obsahuje jediný príkaz: zníženie premennej I o 1. Zrejme po 37 prechodoch cyklu I dosiahne 0 a cyklus skončí. Čo sa stane, keď dáme bodkočiarku za slovo do?
var
I: Integer;
begin
I := 37;
while I > 0 do;
Dec(I);
Image1.Canvas.Font.Height := 30;
Image1.Canvas.TextOut(10, 10, IntToStr(I));
end;
Program sa zacyklí, lebo stále testuje podmienku, či je I väčšie ako 0, pritom vykonáva prázdny príkaz: medzi do a ; je prázdny príkaz, ktorý nerobí nič. Takýto program môžeme zastaviť buď v operačnom systéme v správcovi úloh, alebo v prostredí Lazarus tlačidlom Zastaviť (resp. Ctrl-F2).
Zaujímavá situácia vznikne, keď namiesto Dec() zapíšeme Inc(), t.j. namiesto znižovania pôvodnej hodnoty 37 až na 0, budeme túto hodnotu zvyšovať - na prvý pohľad by sa zdalo, že donekonečna. Lenže celočíselná aritmetika nám dovolí ísť len do čísla 2147483647. Keď túto hodnotu zvýšime o 1, buď program spadne na pretečení, alebo nám dá nezmyselný výsledok číslo -2147483648 (to je najmenšie možné celé číslo). To, ako to dopadne závisí od toho, čí máme alebo nemáme zapnutú kontrolu pretečenia (ako v prvej prednáške o 13!).
var I: Integer; begin I := 37; while I > 0 do Inc(I); Image1.Canvas.Font.Height := 30; Image1.Canvas.TextOut(10, 10, IntToStr(I)); end; |
![]() |
![]() |
Všimnite si, že v oboch prípadoch tento program relatívne dlho trval - vyše 2 miliardy krát sa robil príkaz Inc(I).
Keď už vieme ako funguje while-cyklus, ukážme, ako Pascal v skutočnosti interpretuje for-cykly. Takýto for-cyklus
for premenná := hodnota1 to hodnota2 do begin príkazy; end;
Pascal na to použije pomocnú premennú (nazvali sme ju Koniec), do ktorej si najprv vypočíta koncovú hodnotu. Potom priradí počiatočnú hodnotu cyklu do premennej cyklu. Teraz naštartuje while-cyklus, v ktorom kontroluje, či premenná cyklu neprevyšuje koncovú hodnotu. V tele cyklu najprv vykoná všetky príkazy z tela for-cyklu a na záver zvýši premennú cyklu:
Koniec := hodnota2; premenná := hodnota1; while premenná <= Koniec do begin príkazy; Inc(premenná); end;
Z tejto realizácie vidíme, že for-cyklus, ak je hodnota1 menšia alebo rovná hodnota2, prejde presne hodnota2 - hodnota1 + 1 krát. Napr. takýto cyklus
N := 10;
for I := 1 to N do
begin
Image1.Canvas.TextOut(10, Y, IntToStr(I));
if I > 1 then
N := 4;
Inc(Y, 20);
end;
Tento cyklus prejde vždy 10-krát, aj keď sme v tele cyklu zmenili hodnotu premennej N, ktorá je aj koncovou hodnotou cyklu. Ďalším dôsledkom je aj to, že na výpočet štartovej a koncovej hodnoty môžeme použiť aj premennú, ktorá sa stane riadiacou premennou cyklu. Ukazuje to nasledujúci príklad:
var
I, Y: Integer;
begin
Y := 0;
Image1.Canvas.Font.Height := 20;
I := 37;
for I := I - 1 to I + 1 do
begin
Image1.Canvas.TextOut(10, Y, IntToStr(I));
Inc(Y, 20);
end;
end;
|
![]() |
Uvedomte si, že takýto spôsob zápisu programu je ťažšie čitateľný a takéto konštrukcie neodporúčame používať.
Vstupný riadok
Do formuláru aplikácie môžeme vložiť aj komponent vstupný riadok - s vnútorným menom Edit1. Komponent vyberieme zo štandardnej palety a vložíme niekam do formuláru - vtedy dostane meno Edit1. Pre nás bude najdôležitejšie nastavenie Text, ktoré môžeme meniť nielen v Inšpektore objektov ale aj v programe (v programe použijeme Edit1.Text). Týmto nastavením sa vieme dostať k textu, ktorý sa momentálne nachádza v editovateľnej časti komponentu. Počas behu programu používateľ môže do tohto riadku písať, resp. ho opravovať a program môže tento text ďalej spracovať.
Nasledujúci program po zatlačení tlačidla Button1 text v komponente Edit1 vypíše na náhodnú pozíciu, pričom zmení na náhodnú aj veľkosť písma:
procedure TForm1.Button1Click(Sender: TObject);
begin
Image1.Canvas.Font.Height := Random(30) + 10;
Image1.Canvas.TextOut(Random(250), Random(180), Edit1.Text);
end;
|
![]() |
![]() |
Zrejme sme zatlačili tlačidlo viackrát a menili sme aj text vo vstupnom riadku.
Vstupný riadok môže slúžiť aj na zadávanie čísel, ktoré potom ďalej môžeme spracovať programom. Hodnotu Edit1.Text ale nie je možné priradiť do celočíselnej premennej. Túto textovú hodnotu musíme najprv prekonvertovať na celé číslo. Použijeme štandardnú funkciu StrToInt() (je to vlastne opačná funkcia k IntToStr(), ktorá konvertuje celé číslo na text). Ilustruje to nasledujúci príklad:
Keď sme druhýkrát stlačili Button1, zadali sme text, ktorý nie je správnym textom celého čísla - program spadol a vypísal správu.
Napíšeme program, ktorý zo vstupného riadku prečíta celé číslo a vypíše, či je záporné, nulové alebo kladné:
Všimnite si dva vnorené podmienené príkazy if. Formátovali sme ich podľa pascalovských pravidiel, t.j. vnorené príkazy sú odsunuté vpravo o dve medzery. Keďže pri programovaní aj náročnejších úloh sa veľmi často objavujú vnorené if-príkazy a často je to postupnosť aj viac vnorení, v Pascale (aj v iných programovacích jazykoch) sa to zvykne zapisovať aj takto (tzv. zápis else-if):
if A < 0 then Image1.Canvas.TextOut(10, 10, Format('%d je záporné', [A])) else if A = 0 then Image1.Canvas.TextOut(10, 10, Format('%d je nulové', [A])) else if A = 1 then Image1.Canvas.TextOut(10, 10, Format('%d je rovné jedna', [A])) else Image1.Canvas.TextOut(10, 10, Format('%d je kladné', [A]));
Operácie mod a div môžeme použiť na rozklad čísla na cifry. Nasledujúci príklad ukazuje, ako zistíme poslednú cifru a ako odstránime túto poslednú cifru, t.j. vytvoríme číslo bez poslednej cifry:
Euklidov algoritmus
Tento algoritmus je jeden z najznámejších a najstarších algoritmov. Datuje sa okolo 300 rokov pred n. l. Je to vlastne matematický predpis, ako zistiť najväčší spoločný deliteľ (NSD) dvoch čísel, napr A a B:
- ak sa obe čísla rovnajú, táto hodnota je hľadané NSD
- ak je A > B, tak A znížime o B
- ak je A < B, tak B znížime o A
- toto opakujeme, kým nenájdeme NSD
Zrejme obe hodnoty A aj B musia byť väčšie ako 0, inak sa tento návod môže zacykliť. Zapíšme to pomocou while-cyklu, pričom obe hodnoty prečítame z dvoch vstupných riadkov Edit1 a Edit2:
Samotný výpočet Euklidovho algoritmu je v programe vyznačený červenou. Premenné A0 a B0 sú pomocné len kvôli výpisu v TextOut.
Pozrime sa na výpočet NSD(1000, 3): program najprv 333-krát odpočíta 3 od prvej premennej A, ktorá mala hodnotu 1000. Takto dostávame výsledok 1. Lenže k tomuto istému sa vieme rýchlejšie dostať pomocou zvyšku po delení, t.j. A := A mod B; Takto opravený algoritmus dáva rovnaké výsledky ale je výrazne efektívnejší:
while B > 0 do begin Pom := B; B := A mod B; A := Pom; end;
Neskôr uvidíme tento algoritmus zapísaný pomocou rekurzie.