MQL4 könyv   Operátorok   A 'while' ciklus operátor

A ‘while’ ciklus operátor

Az MQL4-ben igen hasznos lehetőség, hogy benne ciklusokat (hurkokat) szervezhetünk .

Az alkalmazási programok létrehozása közben gyakran használunk ismételt számításokat, melyek javarészt ismétlődő programsorok. Hogy kényelmessé tegyük a programozást, és maga a program is felhasználóbarát legyen ciklus operátorokat használhatunk.Az MQL4-ben két ciklusoperátor van: ‘while’ és ’for’. Ebben a részben az elsőt tárgyaljuk .

A ‘while’ operátor formátuma

A ‘while’ ciklus-operátor teljes formátuma a fejlécből, -ami egy feltételt tartalmaz, és a kapcsos zárójelek közé zárt végrehajtható ciklustörzsből áll.

 while ( Feltétel )   // A ciklusoperátor fejléce
{ // Kapcsos zárójel
Operátor blokk alkotja.. // Az operátor törzs több operátort..
..a ciklus törzset //.. is tartalmazhat
} // Záró kapcsos zárójel

Ha az operátortörzs csak egy operátorból áll a ‘while’ operátorban a kapcsos zárójelek elhagyhatók.

 while ( Feltétel )   // A ciklusoperátor fejléce
 Csak egy operátor van a ciklustörzsben // A ciklustörzs csak egy operátort tartalmaz

A ‘while’ operátor végrehajtás szabályai

Figyelem!

Ameddig a ‘while’ operátor feltétele igaz: A program átadja a vezérlést a ciklustörzs operátorainak; miután a ciklustörzsben minden operátort végrehajtottak, ez átadja a vezérlést a fejlécbe, hogy az tesztelje a feltétel igazságát. Ha a ‘while’ operátor feltétele hamis, a vezérlést át kell adni annak az operátornak amelyik a ‘while’ ciklusoperátort követi.


Vizsgáljunk meg egy példát!

Feladat

12. feladat: számoljuk ki a Fibonacci együtthatót 10 számjegy pontossággal.

Először is, röviden ismerjük meg a Fibonacci együtthatót. Leonardo Fibonacci olasz matematikus, felfedezett egy különös számsorozatot:

1 1 2 3 5 8 13 21 34 55 89 144 233 ...

Ebben a számsorozatban mindegyik szám az őt megelőző két szám összege. Ennek a számsorozatnak van néhány egyedülálló tulajdonsága: A sorozatban levő két egymás utáni szám aránya egyenlő 1.618-cal, míg az arány egy szám és az előző szám között egyenlő 0.618-cal. Az 1.618 arányt Fibonacciról nevezték el, és a fenti sorozatot Fibonacci sorozatnaknevezték el(azt is meg kell jegyezni, hogy a 0.3819 a konjugált Fibonacci szám, amit akkor kapunk, ha azt megszorozzuk önmagával: 0.3819 = 0.618 х 0.618).

A feladatnak nagy pontossággal kell ki számolnia a Fibonacci számot. Ha a Fibonacci együtthatót a Fibonacci sorozat több tíz elemére elemezzük, akkor nyilvánvalóvá válik, hogy a kapott együtthatók az 1.61803398875...  irracionális számhoz alulról és felülről közelítenek . Ha a sorozat növekvő számain végezzük a számításokat, az eredmény eltérése ettől az értéktől egyre kisebb.

Nem tudjuk előre, hogy a Fibonacci sorozat mely elmei azok a számok, ahol a számított együtthatók csak a tizedik számjegy után különböznek. Tehát egy olyan programot kell létrehozni, amely addig keres az együtthatókban, amíg (‘while’) az együtthatók közti különbség 0.0000000001-nél kevesebbet nem lesz.

Ebben az esetben egy scriptet kell írni (fibonacci.mq4) a 12. feladat megoldására, mert a programot nem fogjuk állandóan használni, nem szükséges, hogy folyamatosan működjön. Egyszer csatoljuk a szimbólumablakhoz, a script elvégez minden szükséges számítást (az eredmény bemutatását beleértve), azután azt az ügyfélterminál el fogja távolítani az ablakból.
//----------------------------------------------------------------------------------------
// fibonacci.mq4
// The code should be used for educational purpose only.
//----------------------------------------------------------------------------------------
int start() // Special function start()
 {
//----------------------------------------------------------------------------------------
 int i; // Formal parameter, counter
 double
 A,B,C, // Numbers in the sequence
 Delta, // Real difference between coefficients
 D; // Preset accuracy
//----------------------------------------------------------------------------------------
 A=1; // Initial value
 B=1; // Initial value 
 C=2; // Initial value
 D=0.0000000001; // Set accuracy
 Delta=1000.0; // Initial value
//----------------------------------------------------------------------------------------
 while(Delta > D) // Cycle operator header
 { // Opening brace of the cycle body
 i++; // Counter
 A=B; // Next value
 B=C; // Next value
 C=A + B; // Next value
 Delta=MathAbs(C/B - B/A); // Search difference between coefficients
 } // Closing brace of the cycle body
//----------------------------------------------------------------------------------------
 Alert("C=",C," Fibonacci number=",C/B," i=",i);//Display on the screen
 return; // Exit start()
 }
//----------------------------------------------------------------------------------------

A program kezdetén a változókat deklaráljuk (és magyarázzuk). A következő sorokban az A, B és C változók számszerű értékeit adják Fibonacci sorozat a kezdeti értékét. Itt tudni kell azt, hogy maga a sorozat egész számokat tartalmaz, csak a hányadosuk valós szám (tört szám). Ha a hányadosra az int típust használnánk, lehetetlen volna kiszámolni Fibonacci együtthatót, például: 8/5 = 1 (egész szám 1, a tört rész nélkül). Úgyhogy ebben az esetben double típusú változókat használunk. A ciklusoperátor így néz ki:

 while(Delta > D) // Cycle operator header
 { // Opening brace of the cycle body
 i++; // Counter
 A=B; // Next value
 B=C; // Next value
 C=A + B; // Next value
 Delta=MathAbs(C/B - B/A); // Search difference between coefficients
 } // Closing brace of the cycle body

Figyeljük meg a ‘while’ ciklus operátor blokkdiagramját:


42. ábra: A ’while’ operátor végrehajtásának blokkdiagramja a fibonacci.mq4 programban.


Induláskor a ciklus operátor teszteli a feltétel. A ciklust ismételten végre fogja hajtani amíg (‘while’) a feltétel (Delta>D) igaz. Sokkal jobb megfogod érteni programkódot, ha fennhangon olvasod a ‘while’ operátor kulcsmondatát (a végrehajtási szabályt). Például, ha a ‘while’ operátorról van szó: ”Mindaddig amíg…., hajtsd végre a következőt:…”  Ebben az esetben, a ‘while’ operátor fejléce a következő : amíg Delta nagyobb, mint D, hajtsd végre a következőt... , Ha a feltétel igaz, a program végrehajtja a ciklustörzsben lévő programsorokat majd újból elemzi a feltételt.

A fibonacci.mq4 fenti példája szerint a vezérlést megkapta a ‘while’ ciklusoperátor, a feltételben szereplő változók értékei 1000.0 és 0.0000000001; tehát a feltétel igaz a ciklusoperátornak szóló első hívásnál. Ez azt jelenti, hogy miután a feltételt teszteltük, a vezérlés át fog kerülni ciklus operátortörzsben lévő első operátorhoz.

A példánkban ez a következő operátor:

 i++; // Counter

A következő három sorban a sorozat újabb elemei lesznek kiszámolva:

 A = B; // Next value
 B = C; // Next value
 C = A + B; // Next value

Könnyű belátni, hogy a változók felveszik a következő (legközelebbi nagyobb) elem értékét. Mielőtt a ciklusoperátort végrehajtjuk, A, B és C értéke egyenlő volt 1.0-val, 1.0-val és 2.0-val. Az első iterációnál (ismétlés) ezek a változók felveszik az 1.0, 2.0 és 3.0 értékeket.

Az iteráció (ismétlés) néhány számítás ismételt végrehajtása; jelen esetben a ciklus-operátortörzset alkotó programsorok végrehajtása.

A következő sorban kiszámítjuk a különbséget a Fibonacci számok között, a (C/B) és (B/A) hányadosra kapott eredmény alapján:

 Delta = MathAbs(C/B - B/A); // Search difference between coefficients

Ebben az operátorban a beépített MathAbs() függvényt használjuk, amely kiszámítja a kifejezés abszolút értékét. Ahogy fent megemlítettük, a Fibonacci együtthatók közelítő értéke a számítások során a tényleges értékhez képest vagy nagyobb értéket vesz fel. Ezért a szomszédos együtthatók közti különbség lehet negatív vagy pozitív érték. Ugyanakkor csak az eltérés nagyságával és nem az irányával foglalkozunk (az abszolút érték). Így, bármilyen  irányú a Fibonacci szám aktuális számított értékének az eltérése, a MathAbs(C/B – B/A) vagyis a Delta változó értéke mindig pozitív.

Ez az operátor az utolsó a ciklustörzset alkotó operátorok listájában. Ezt követi egy záró kapcsos zárójel a következő sorban. Miután az utolsó operátort a ciklustörzsben végrehajtottuk, a vezérlést megkapja a ciklusoperátor fejléce, hogy tesztelje a feltételt. Ez az a fő esemény, ami meghatározza a ciklusoperátor lényegét. A ciklusoperátor feltételének igaz vagy hamis volta alapján a vezérlést a következő iteráció (ismételt végrehajtás) vagy a ciklusoperátoron kívüli, következő operátor fogja kapni.

Az első ismétléseknél kiderül, hogy a Delta változó számított értéke nagyobb, mint a D változó élőre beállított értéke. Vagyis ez azt jelenti, hogy a feltétel (Delta > D) igaz, tehát a vezérlést meg fogja kapni a ciklustörzs azért, hogy végrehajtsa a következő ismétlést (iterációt). Minden változó, ami szerepet játszott a számításokban, új értéket fog kapni: amint a ciklustörzs végrehajtása befejezödik a vezérlés megint átkerül a fejlécbe azért, hogy tesztelje a feltétel teljesülését.

Ez az eljárás addig fog folytatódni, amíg (‘while’) a ciklusoperátor feltétele hamissá válik. Amint Delta a változó értéke kisebb vagy egyenlő, mint D értéke a (Delta > D) feltétel nem igaz tovább. Ennek következtében a vezérlés átkerül a ciklusoperátoron kívüli következő a sorba:

 Alert("C=",C," Fibonacci number=",C/B," i=",i);//Display on the screen

Végül az Alert () ablakban a következő üzenet fog megjelenni:

С=317811 Fibonacci number=1.618 i=25


Ez azt jelenti, hogy a kívánt pontosságot a 25. ismétlésnél értük el, a Fibonacci sorozat elemének maximális értéke a számítások során 317811 volt és a Fibonacci együttható, ahogy vártuk 1.618. Ez az üzenet  jelenti a feladat megoldását.

Itt jegyezzük meg, hogy az MQL4 a számításokat 15 számjegy pontossággal végezte. Ugyanakkor a Fibonacci együttható értékét csak 3 tizedes pontossággal látjuk. Ez abból fakad, hogy az Alert() függvény 4 tizedes jegyet használ és a tizedesek végén a nullákat nem mutatja. Ha a Fibonacci számot egy bizonyos, előre definiált pontossággal szeretnénk látni, meg kell változtatnunk a kódot:
 Alert("C=",C," Fibonacci number=",C/B*10000000," i=",i);// Message

A következőt jól meg kell jegyezni:

Figyelem!

Elképzelhető, hogy a feltétel, amit a ciklus operátor fejlécben megadtunk mindig igaz marad. Ennek eredménye egy végtelen ciklus (looping) kialakulása.

Looping (hurkolódás, végtelen ciklus) a ciklustest operátorainak folytonosan ismételt végrehajtása; ez egy olyan kritikus helyzet, ami egy hibás algoritmus végrehajtásából ered.

Ha egyszer egy összehurkolódás kialakul, a program vég nélkül végrehajtja a ciklustörzs operátorainak blokkját. Lent egy egyszerű példa az összehurkolt ‘while’ ciklusoperátorra:

 int i=1; // Formal parameter (counter)
while (i > 0) // Cycle operator header
i++; // Increment of the value of i

A fenti példában, az i változó értéke növekszik (inkrementálódik) minden ismétlésnél. Ezért a feltétel soha sem fog hamissá válni. Hasonló a helyzet, ha semmit nem számolunk ki az operátor testben. Például, a lenti kódban:

 int i=1; // Formal parameter (counter)
while (i > 0) // Cycle operator header
Alert("i= ",i); // Display on the screen

Az i változó értéke a ciklusban nem változik. A következő üzenet fog megjelenni a képernyőn mindegyik ismétlésnél:

i= 1

Ez az eljárás vég nélkül fog ismétlődni. Ha egyszer egy végtelen ciklus kialakul, a vezérlés nem tud abból kilépni. Ez a helyzet különösen veszélyes a kereskedő Expert Advisorban és a kereskedő scriptekben. Ilyen esetben a környezeti változókat általában nem frissítik, mert a különleges függvény nem fejezi be a működésé, és a kereskedő nem érzékeli az összehurkolódást. Ennek az lesz az eredménye, hogy a program fölötti ellenőrzés megszűnik és a megbízások nem teljesülnek.

A programozónak az olyan eseteket meg kell akadályoznia, amelyekben egy ellenőrizetlen összehurkolódás lehetősége fennáll. Nincs olyan technika ami programozható módon segítene felfedezni ezt a helyzetet sem a fordításnál, sem a végrehajtásánál. Az egyetlen lehetséges módszer az ilyen algoritmikus hibák észlelésére a kódok vizsgálata során a logikus érvelés és a józan ész.