Példák algoritmusokra
Az tárgyalt algoritmusok leírását a legtöbb esetben rövid JavaScript programokkal is bemutatjuk. A példák kipróbálásához felhasználható online JavaScript interpreter:
Online JavaScript Interpreter by Peter Jipsen, Chapman University (January 2013).
http://math.chapman.edu/~jipsen/js/ (2020-11-19)Megjegyzés: Ha a fenti link valamilyen oknál fogva nem működik, használjuk az alábbi linket.
A JavaScript programok folyamatábráját megjeleníthetjük az alábbi webes alkalmazás segítségével:
Live code editor. Created by Bogdan Lyashenko.
https://bogdan-lyashenko.github.io/js-code-to-svg-flowchart/docs/live-editor/index.html (2022-10-02)A folyamatábra a 'for' ciklust nem megfelelően ábrázolja, ezért érdemes ezeket mindig átírni 'while' ciklusra, mielőtt megjelenítenénk a program folyamatábráját.
Bináris szám átalakítása decimális számmá JavaScript program segítségével
Példa: 11012 = ?10
Megoldás:
számjegy helyi érték szorzat 1 23=8 8 1 22=4 4 0 21=2 0 1 20=1 1 Összesen 13 Eredmény:
11012 = 1310Ellenőrzés:
1310 = 8 + 4 + 1 = 1*23 + 1*22 + 0*21 + 1*20 = 11012 (ok)
A fenti algoritmust megvalósító JavaScript program:
// bináris szám átalakítása decimális számmá var x="1101"; writeln("Bináris szám: "+x); writeln(); var d=0; var helyiertek=1; for(var i=1;i<x.length;i++) { helyiertek*=2; } for(var i=0;i<x.length;i++) { var sz; if(x[i]=="1") { sz=1; } else { sz=0; } writeln(" Számjegy : "+sz); writeln(" Helyi érték: "+helyiertek); var r=sz*helyiertek; writeln(" Részösszeg: "+r); d+=r; helyiertek/=2; } writeln(); writeln("Decimális szám: "+d); writeln("__________");
A fenti JavaScript program egyszerűsített változata és ennek a folyamatábrája a következő:
// bináris szám átalakítása decimális számmá (ver 2.0) var x="1101"; writeln("Bináris szám: "+x); writeln(); var d=0; var helyiertek=1; var i=1; while(i<x.length) { helyiertek=helyiertek*2; i=i+1; } i=0; while(i<x.length) { var sz; if(x[i]=="1") { sz=1; } else { sz=0; } var r=sz*helyiertek; d=d+r; helyiertek=helyiertek/2; i=i+1; } writeln("Decimális szám: "+d); writeln("__________");A fenti JavaScript programokban előforduló fontosabb programnyelvi szerkezetek rövid magyarázata:
// ...
- megjegyzés ("koment") megadása; a
//
jelek után következő szöveget a JS interpreter figyelmen kívül hagyja- ha többsoros megjegyzést szeretnénk írni, vagy szeretnénk (például mert egy programhiba előfordulásának helyét szeretnénk meghatározni), hogy a program egy adott részletét a JS interpreter ne vegye figyelembe, használjuk a
/* ... */
jeleket (amelyek mindig párban fordulnak elő)
var x="1101";
- a
var
kulcsszó egy ún. deklarációs utasítást vezet be, amelyben egy új változót hozunk létre (pl. az 'x' nevű változót)
– a változókban egy meghatározott típusú adatot tárolhatunk
– a 'var' deklarációs utasításban vesszővel elválasztva több változót is deklarálhatunk- a JS legfontosabb (elemi) adattípusai a következők:
- számok (Number), ezen belül
- egész számok (pl. x=3; vagy x=-10;)
- valós számok (pl. x=-10.0; vagy x=13.945;)
- a valós számokat megadhatjuk m*10k alakban is, ahol 'm' az ún. mantissza, 'k' az ún. karakterisztika (pl. x=3e-4; a 3*10−4 valós számot adja meg)
- logikai értékek (Boolean) (pl. x=true; vagy x=false;)
- karakterek, ill. karakterláncok vagy stringek (pl. x="a"; vagy x="hello";)
- a stringeket megadhatjuk aposztrófok között is, pl. x='xyz'; módon
- a stringek karaktereit balról sorszámozzuk, 0-tól kezdődően (vagyis a string bal szélső karaktere a 0-dik sorszámú karakter, amelyre pl. x[0] módon hivatkozhatunk)
- a JavaScript nyelvben a stringként megadott változók csak olvashatóak (tehát például az x="alma"; értékadás után az x[0]="e"; utasítás nem változtatja meg az 'x' string 0-dik karakterét)
- ha egy stringben szeretnénk egy idézőjelet elhelyezni, akkor a
\"
karakterkombinációt, ún. "escape szekvenciát" kell alkalmaznunk (a '\' jelet ebben a kontextusban "escape" karakternek nevezzük)- ha egy stringben szeretnénk egy Unicode kóddal megadott karaktert elhelyezni, akkor a
\uxxxx
karakterkombinációt kell alkalmaznunk, ahol 'xxxx' a karakter kódját jelenti (hexadecimális számként megadva)- azonos típusú adatok és változók között különböző műveleteket végezhetünk, és a műveletek eredményét eltárolhatjuk egy változóban (pl. y=3*x+5; vagy x=x+1;)
- a JS néhány fontos művelete a következő:
- számok esetén a szokásos alapműveletek
- összeadás (pl. x=2+4;)
- kivonás (pl. x=3−5;)
- szorzás (pl. x=2*3.14;)
- osztás (pl. x=y/7;)
- ha egy aritmetikai alapművelet egy változó korábbi értékének módosítását eredményezi, a műveleteket megadó utasításokat rövidíthetjük; például
○ i=i+1; helyett i+=1; vagy i++; írható (ún. inkrementálás)
○ x=x+5; helyett x+=5; írható
○ i=i−1; helyett i−=1; vagy i−−; írható
○ x=x−5; helyett x−=5; írható
○ x=x*5; helyett x*=5; írható
○ x=x/5; helyett x/=5; írható- logikai értékek esetén a logikai alapműveletek (amelyekkel minden további logikai művelet kifejezhető)
- logikai 'és' (pl. x=a&&b;)
- logikai 'vagy' (pl. x=a||b;)
- logikai 'nem' (pl. x=!a;)
- implikáció (pl. x=!a||b;)
- ekvivalencia (pl. x=(!a||b)&&(!b||a); vagy egyszerűen x=(a==b);)
- karakterek, ill. karakterláncok vagy stringek esetén az összefűzés vagy konkatenáció (pl. x="A szorzat értéke: "+a*b; vagy x="Hello "+y+"!";)
- az
=
szimbólum egy ún. értékadó operátor, amely az '=' jel jobb oldalán szereplő értéket hozzárendeli az '=' jel bal oldalán megadott változóhoz (például az x="1101"; értékadó utasítás végrehajtásakor a JS interpreter az 'x' nevű változó korábbi értékét felülírja a "1101" karaktersorozattal)
- ha az '=' értékadó operátort a deklarációs utasításban, a változó létrehozásával egyidejűleg adjuk meg, kezdőértékadásról beszélünk
- a
"..."
szerkezetben az idézőjelek között egy karaktersorozatot vagy stringet adunk meg; a stringeket határoló idézőjelek mindig párban fordulnak elő (konkrétan megadott karakterláncok esetén a 'string' helyett gyakran használjuk a 'literál' terminust is)
- a stringekben előforduló karakterekhez balról jobbra haladva egy 0-val kezdődő sorszámot, ún. indexet rendelünk
- ha az index értékét az 'i' változóban tároljuk, az 'x' változóban tárolt string i-dik karakterét x[i] módon jelöljük (vagyis az indexet szögletes zárójelek között adjuk meg)
- az 'x' változóban tárolt string hosszát az x.length kifejezés adja meg
- az 'x' változóban tárolt string karaktereinek indexe a [0 , (x.length−1)] zárt intervallumba eső természetes szám
- minden JS utasítást
;
jellel zárunk le
writeln("Bináris szám: "+x);
- a
writeln
azonosító egy kiíró eljárást jelöl; a zárójelek között megadott string a 'writeln' eljárás egy (input) paramétere, amit a JS interpreter a jobb oldali panelben fog kiírni- a "Bináris szám: " stringet és az 'x' változó (string típusú) értékét a
+
ún. összefűző (vagy konkatenációs) operátorral egy összefüggő stringgé alakítjuk, hogy a writeln(...) eljárás segítségével a két stringet együtt, egy sorban ki tudjuk írni (jegyezzük meg, hogy a writeln(...) eljárásban csak egy stringet tudunk megadni az eljárás paramétereként)
for(var i=1;i<x.length;i++) {...}
- a
for
kulcsszó egy ún. rögzített lépésszámú ciklust ad meg; ennek lényege, hogy ameddig a 'for' után megadott logikai feltétel (i<x.length) teljesül, a számítógép a kapcsos zárójelek között megadott utasításokat újra és újra ("ciklikusan") végrehajtja
- a
{...}
kapcsos zárójelek egy ún. utasításblokkot adnak meg, amely nulla, egy vagy több, egyenként pontosvesszővel lezárt utasításból áll (az utasításblokkot úgy érdemes elképzelnünk, hogy a JS interpreter az utasításblokkban megadott utasításokat lényegében egy "összetett" utasításnak tekinti)- a {...} utasításblokkban megadott utasítások alkotják az ún. utasításciklust, amit a 'for' utasítás ciklikusan ismételni fog
- a 'for' utasítás a 'for' kulcsszó után megadott (...) fejrésszel és {...} utasításblokkal együtt alkot egy utasítást (ezért például tilos a for(...) és a {...} utasításrészek közé pontosvesszőt tenni)
- a var
i
=1; deklarációs és kezdőértékadó utasítás hatására a 'for' ciklus elindulása (vagyis az első utasításciklus végrehajtása) előtt a JS interpreter létrehozza az 'i' nevű ciklusváltozót és beállítja az 'i=1' kezdőértéket- az
i<
x.length ún. ciklusfeltételt a JS interpreter minden utasításciklus végrehajtása előtt megvizsgálja ("kiértékeli"):
- ha az értékelés 'igaz' ('true'), azaz ha a ciklusfeltétel teljesül, a számítógép az utasításciklust (először, ill. ismételten) végrehajtja
- ha az értékelés 'hamis' ('false'), akkor a számítógép "kilép" a ciklusból, azaz a program a 'for' utasítás után következő utasítás végrehajtásával folytatódik
- az utasításciklusban megadható continue; utasítás végrehajtásakor a JS interpreter figyelmen kívül hagyja a ciklusmag utána következő utasításait, és befejezi az aktuális ciklust (a ciklusváltozó értékének módosításával, ld. alább)
- az utasításciklusban megadható break; utasítás végrehajtásakor a JS interpreter azonnal kilép a ciklusból
- az
i++;
utasítás az utasításciklus utolsó utasítása, amely eggyel megnöveli a ciklusváltozó értékét ("inkrementálja" a ciklusváltozót); a ciklusváltozó növelését, ill. általánosan fogalmazva a ciklusváltozó értékének módosítását a számítógép az utasításciklusban levő utasítások végrehajtása után mindig automatikusan végrehajtja
- az i++; utasítás egyenértékű az i=i+1; utasítással
- a ciklusváltozó segítségével a számítógép lényegében "nyilvántartja", hányadik ciklus következik (a ciklus végrehajtásainak számlálása rendszerint 0-val vagy 1-gyel kezdődik); emiatt kapta a 'for' ciklus a "rögzített lépésszámú ciklus" elnevezést
- mivel a ciklusváltozó kezdőértéke esetünkben egy (vö. i=1;), az 'x.length' egy rögzített érték (pl. x="1101"; esetén 4), és a ciklusváltozó értéke minden utasításciklus után eggyel nő (vö. i++), a ciklus egy idő után biztosan befejeződik, mert 'i' értéke eléri az 'x.length' kifejezés értékét (azaz elkerüljük az ún. végtelen ciklus hibát)
A 'for' ciklus egyik tipikus alkalmazása egy string karaktereinek egyenként történő feldolgozása (pl. kiírása egymás alá, külön sorokban):
// egy string karaktereinek kiírása egymás alá var x="1101"; for(var i=0;i<x.length;i++) { writeln(x[i]); } writeln("___________");Ezt a JavaScript programrészletet érdemes memorizálni.
A fenti példaprogramot módosíthatjuk úgy, hogy csak a string első szavát írjuk ki egy sorban. (Tétetezzük fel, hogy az első szó végét egy szóköz jelzi.)
// egy string első szavának kiírása var x="Hello Kata hogy vagy?"; for(var i=0;i<x.length;i++) { if(x[i]==" ") { break; } write(x[i]); } writeln(); writeln("___________");Ennek a példaprogramnak egy valamivel összetettebb variációja, hogy először keressük meg a string első szavát, majd a string első szó után következő karaktereit írjuk ki egy sorban. Tétetezzük fel, hogy az első szó végét most is egy szóköz jelzi. A program érdekessége a 'k' logikai változó, amelynek 'false' értéke azt jelzi, hogy még nem találtuk meg az első szót, 'true' értéke pedig azt, hogy megtaláltuk, és kezdődhet az első szó utáni karakterek kiírása.
// egy string első szava _utáni_ részének kiírása var x="Hello Kata hogy vagy?"; var k=false; // még _nem_ értünk a végére az első szónak for(var i=0;i<x.length;i++) { if(x[i]!=" " && !k) { continue; } if(x[i]==" " && !k) { k=true; // az első szó végére értünk continue; } write(x[i]); } writeln(); writeln("___________");Jegyezzük meg, hogy a logikai változók kiválóan használhatók egy programban különböző események bekövetkezésének jelzésére.
if(x[i]=="1") {...} else {...}
- az
if
(...) {...}else
{...} szerkezet egy ún. kétirányú elágaztató utasítás (vagy kétirányú szelekció), amelyben
- az 'if' kulcsszó után a (...) kerek zárójelek között egy logikai feltétel szerepel
- az 'if(...)' szerkezet után a {...} kapcsos zárójelek között egy utasításblokkot adhatunk meg (első utasításblokk)
- az 'else' kulcsszó után pedig a {...} kapcsos zárójelek között egy másik utasításblokkot adhatunk meg (második utasításblokk)
- az 'if-else' utasítás lehetővé teszi, hogy a megadott logikai feltételtől függően a program más-más utasításokat hajtson végre:
- ha az 'if' után megadott feltétel értéke igaz ('true'), akkor a program az 'if(...)' szerkezet után (és az 'else' kulcsszó előtt) levő első utasításblokk utasításainak a végrehajtásával fog folytatódni
- ha az 'if' után megadott feltétel értéke hamis ('false'), akkor a program az 'else' kulcsszó után következő második utasításblokk utasításainak a végrehajtásával fog folytatódni
- az if-else utasításban az 'else' kulcsszó és az utána következő utasításblokk elhagyható; ilyenkor egyirányú elágaztató utasításról (vagy egyirányú szelekcióról) beszélünk
x[i]=="1"
- az 'if' utasítás után megadott logikai feltételt sok esetben azonos típusú adatok és változók értékének az összehasonlításával adjuk meg
- a JS esetében a fontosabb összehasonlító operátorok a következők:
- számok esetén a "standard" összehasonlító operátorok a következők:
== ("egyenlő"), <, ≤, >, ≥, != ("nem egyenlő")
- ha két érték összehasonlításakor előfordulhat az, hogy az összehasonlítandó értékek "tartalmilag" azonosak, de különböző típusúak⇒, akkor használhatjuk az === ("azonos típusú és egyenlő"), valamint a !== ("nem azonos típusú vagy nem egyenlő") operátorokat is; például
– az ("1"==1) logikai kifejezés igaz, de a ("1"===1) logikai kifejezés hamis
– a ("1"!=1) logikai kifejezés hamis, de a ("1"!==1) logikai kifejezés igaz- logikai értékek esetén a == ("egyenlő") és != ("nem egyenlő") operátorok használatának van értelme (jegyezzük meg, hogy az == operátor a logikai ekvivalenciának felel meg)
- karakterek, ill. stringek esetén főként a == ("egyenlő") és != ("nem egyenlő") operátorok használatosak
- karakterek, ill. stringek esetén a számok esetében használt többi összehasonlító operátor is használható, de csak bizonyos óvatossággal, mivel ilyenkor az összehasonlítás eredménye (ti. a karakterek, ill. stringek alfabetikus, ún. "lexikografikus" sorrendje) függ a karakterek kódolásától
A bináris egész számokhoz hasonlóan tudjuk a bináris törtszámokat átváltani tizedestörtekké. A különbség csak az, hogy a törtszámok helyiértékei 2 negatív egész hatványai lesznek (a 2−1=1/2 helyiértéktől kezdődően).
Elég csak olyan számokkal foglalkoznunk, amelyek pozitívak és 1-nél kisebbek (azaz egész részük zérus), mivel egy bináris szám egész részét és törtrészét külön-külön átalakíthatjuk decimális számmá.
Példa: 0.11012 = ?10
Megoldás:
számjegy helyi érték szorzat 1 2−1=1/2 1/2 1 2−2=1/4 1/4 0 2−3=1/8 0 1 2−4=1/16 1/16 Összesen 13/16 Eredmény:
0.11012 = 13/1610 = 0.812510Ellenőrzés:
0.812510 = 0.5 + 0.25 + 0.0625 = 1*2−1 + 1*2−2 + 0*2−3 + 1*2−4 = 0.11012 (ok)
A fenti algoritmust megvalósító JavaScript program:
// bináris törtszám átalakítása decimális törtszámmá (tizedestörtté) /* feltétel: a bináris törtszám pozitív és 1-nél kisebb, azaz 0<x<1 teljesül */ var x="0.1101"; writeln("Bináris törtszám: "+x); writeln(); var d=0; var helyiertek=1/2; for(var i=2;i<x.length;i++) { var sz; if(x[i]=="1") { sz=1; } else { sz=0; } writeln(" Számjegy : "+sz); writeln(" Helyi érték: "+helyiertek); var r=sz*helyiertek; writeln(" Részösszeg: "+r); d+=r; helyiertek/=2; } writeln(); writeln("Decimális törtszám: "+d); writeln("__________");