Megjegyzések. Írni utálunk, ezért törekszünk az újra felhasználható programrészekre. Függvények a matematikában és Jávában. Paraméterek, visszatérési értékek és változó láthatósági szabályok.
Programjaink most már kezdenek kellõen bonyolultak lenni ahhoz, hogy magyarázat nélkül ne értsük õket. Minden programozási nyelv, köztük a Jáva is lehetõséget ad arra, hogy ember számára értelmes magyarázó szövegeket, megjegyzéseket tegyünk a kódba. A megjegyzéseket a számítógép egyszerûen figyelmen kívül hagyja, semmilyen hatása nincsen a program mûködésére. Nem is neki szólnak, hanem a program olvasójának. Jávában kétfajta megjegyzés van. Az egyik /* karakterekkel kezdõdik és a legközelebbi */ karakterekig tart, a programban bárhol állhat, több soros is lehet. Pl.
/* Itt egy megjegyzés */
i = 1; /* A sor végén egy megjegyzés */
/* Hosszú,
több sort
átfogó megjegyzés
*/
i /* a változó, amit használunk */ = /* értékadó
utasítás */ 2 /* 2 egy jó érték */;
Az utolsó variációt nem kell követendõ példának tekintened, csak azt akartam vele megmutatni, hogy ez a fajta megjegyzés tényleg mindenhol lehet. A másikfajta megjegyzést // jelek vezetik be és a sor végéig tart. Kevesebbet kell írni vele, rövid megjegyzéseknél ezért szeretik. Példák:
// Egy rövid kis megjegyzés
i = 3; // Végül is igazában 3-at szeretnénk i-be
// Ha hosszú megjegyzést akarunk,
// Minden sor elejére kell a //
// jel.
Írjunk egy programot, ami kiírja az y=x2 függvény értékeit x=(-1,1) intervallumban, 0.1-es lépésenként. Megjegyzésekkel tedd világosabbá, mikor mi történik! A feladat nem okozhat nehézséget, azért a biztonság kedvéért ellenõrizd a megoldást!
A megoldásban felhasználtunk egy újdonságot, a += operátort. Ez az operátor hozzáadja a bal oldalán levõ változóhoz a jobb oldalán levõ értéket, tehát kiveszi a változó értékét, hozzáadja az operátor jobb oldalán levõ kifejezés értékét és visszatárolja a változóba.
x += 0.1;
tehát egyenértékû
x = x + 0.1;
kifejezéssel.
A kiírásban furcsa eredményeket találhattál, pl. íme egy részlet:
... -0.20000000000000015^2=0.04000000000000006 -0.10000000000000014^2=0.01000000000000003 -1.3877787807814457E-16^2=1.9259299443872359E-32 0.09999999999999987^2=0.009999999999999974 ...
Nagyjából stimmel, de mik ezek a furcsa értékek a végén? És pláne, miért nem kapunk 0-t (habár 10-16 elég közel van hozzá ...)? Tudnod kell, hogy a számítógép számára csak az egész, int értékek pontosak. Mivel a gép másként tárolja a számokat, mint az ember, nem biztos, hogy az olyan szép, kerek értékek, mint a 0.1 a gép számára is ugyanolyan szépek. A 0.1 pont egy olyan szám, amit a gép nem tud teljesen pontosan ábrázolni, ezért az összeadások során apró hibák halmozódnak fel. Éppen ez okból a lebegõpontos számokat sose vizsgáljuk egyenlõségre, mert könnyen lehet, hogy az egyenlõség sohase teljesül. Esetünkben például x sohase lesz pontosan 0 vagy 1, ezért a furcsa határértékösszehasonlítás a for ciklusban. Hadd ismételjem meg, hogy ez a probléma csak a lebegõpontos számoknál léphet fel, egészeknél soha, ez egy újabb ok arra, hogy mindenhol egészeket használjunk, ahol csak lehet.
Akárhogy is, nem erre akartam kilyukadni. Maga a kiszámítandó függvény a program közepében van, ha cserélni akarnánk, ki kellene keresnünk a programszövegbõl. Rosszabb, ha a függvény netán bonyolultabb lenne és nem lehetne egy sorban kiszámolni, netán esetleg belsõ változókat használna, a kiszámítandó függvény kódja teljesen összekeveredne a táblázatnyomtató program kódjával. Ezen okból a Jáva rendelkezésünkre bocsátja a saját függvények definiálásának lehetõségét. Igazából már van két saját függvényünk, de azok vadító kék színben tündököltek. Lássuk elõzõ programunk módosítását olymódon, hogy az y = x2 számítását végzõ részt kiemeljük saját függvénybe!
public class x2ertek_2 {
double fuggveny( double xi ) {
double yi;
yi = xi * xi;
return yi;
}
public void prog( String
args[] ) {
double x;
for( x = -1 ; x < 1.001 ; x += 0.1 ) {
System.out.println( x+"^2="+fuggveny(
x ));
}
}
public static void main( String
args[] ) {
x2ertek_2 e = new x2ertek_2();
e.prog( args );
}
}
Ha a programot lefuttatjuk, persze ugyanazt az eredményt kapjuk, mint az elõzõ példában. Mik akkor a változások? Vegyük mindenekelõtt észre a kék sorok drasztikus megfogyatkozását! Vegyük továbbá észre, hogy a táblázatnyomtató ciklusunkban könnyed eleganciával kijelentettük, hogy fuggveny( x ) által visszaadott értéket is ki akarjuk írni. Ez egy függvényhívás.A függvényhívás során a számítógép egy alprogram végrehajtásával folytatja munkáját. Az alprogramot valahol lezárják egy visszatérõ utasítással és megmondják, mi az érték, amit az alprogram visszaad. Ekkor a számítógép elõkeresi, hol hagyta abba a fõprogram végrehajtását és a függvényhívást helyettesíti azzal az értékkel, amit az alprogram visszaadott. A függvény tehát bármilyen kifejezésben állhat, ahol a függvény visszatérési értékének típusa megegyezik az adott kifejezésben várt adattípussal. Például ha van egy függvényünk, ami double-t ad vissza, akkor az felhasználható double számokkal dolgozó kifejezésben.
double fuggv() {
...
}
...
double x;
x = 3.14*fuggv()+2.5;
Maga a függvény deklarációja bárhol lehet a programban, a függvényhívás elõtt és után is. Tilos azonban ugyanazt a függvényt kétszer deklarálni ugyanazzal az aláírással vagyis ugyanazzal a névvel, visszatérési értékkel és paraméterlistával. Azonos nevû, de különbözõ aláírású függvények (tehát például ahol az egyiknek nincs paramétere, a másiknak pedig van) különbözõnek számítanak, mert a Jáva a függvényhívás alapján rájön, hogy melyik függvényt kell meghívnia. Példa:
// Elsõ függvény
int fuggv() {
...
}
// Második függvény
int fuggv( int i ) {
...
}
int i = fuggv(); // Ez az elsõ függvényt
hívja meg
int k = fuggv( 2 ); // Ez a második függvényt
hívja meg
A függvénynek lehet egy speciális visszatérési értéke, a void. Ez azt jelenti, hogy a függvény nem ad vissza értéket, az ilyen függvényt nem lehet kifejezésben felhasználni, de kifejezésen kívül meg lehet hívni. Pont ezen a módon kell alprogramokat, procedurákat definiálni.
void fuggv2() {
...
}
...
fuggv2();
A függvényeknek lehetnek bemeneti paramétereik is. Ezek azok az értékek, amelyeket átadunk az alprogramnak, hogy számoljon belõle kimeneti értéket. A bemeneti paramétereket a függvényfejben soroljuk fel.
double fuggv3( double elso_param, int masodik_param ) {
double eredm;
...
return eredm;
}
...
double eredm;
eredm = fuggv3( 3.14, 4 );
Amikor a függvényt meghívod, bonyolult dolgok játszódnak le.
Hasonlatos ez ahhoz, mint amikor a cikkedhez ki akarsz számolni egy értéket, de csak a szám érdekel. Néhány sajtpapíron elkészíted a számításokat, a számot beírod a cikkbe, majd a sajtpaírokat eldobod. Így mûködik a függvény is, a részeredmények érdektelenek a függvény lefutása után és ami még fontosabb, a függvény belsõ ügyei nem zavarják a program futását.
A függvénybõl természetesen újabb függvényt is meghívhatsz és a hívásra ugyanazok a szabályok vonatkoznak. Ezt nem csinálhatod a végtelenségig, valamekkora korláta van annak, milyen mélységben hivogathatják a függvények egymást, de ez sok ezres mélység.
Lássuk, megértetted-e!
Olvasd el az itt látható programot és mondd meg nekem, mi a nyomtatási kép! Utána próbáld is ki és találd ki az okát, ha netán tévedtél volna. Segítség: nézd meg, melyik függvényhívás melyik fuggv függvényt hívja meg. Ahol a függvényhívásban paramétert adunk át, ott a paraméterrel rendelkezõ fuggv fut, ahol nem, ott a paraméter nélküli.
A megjegyzések használata persze magánügy, de talán a fenti példa is demonstrálja, hogy legalább a függvények fejét (tehát a deklarációjának az elejét, a visszatérési értékének, nevének és paramétereinek megadását) mindenképpen ajánlott megjegyzéssel ellátni, milyen paramétert vár a függvény, azokkal mit csinál és mit ad vissza.
Bergengóciában az adórendszert lényegesen leegyszerûsítették és a Totális Adótábla XXVIII. lapja a következõképpen néz ki:
-100 fbtk* | a jövedelem 9%-a |
100-250 | 9+a 100 fbtk fölötti rész 13%-a |
250-750 | 30+a 250 fbtk fölötti rész 25%-a |
750- | 180+a 750 fbtk fölötti rész 50%-a |
*- fbtk: konvertibilis fabatka, éves szinten
Az utolsó pillanatban a Tüntetõ Bergengóc Anyák Antidemokratikus Szövetségének sikerült keresztülvinnie követeléseit és a családosokoknak kedvezõ intézkedésekkel egyszerûsítették a táblát. Ezek szerint a 1 gyerek nevelése esetén az adó 2%-át, kettõ esetén 8%-át, 3 és a felett gyerekenként 4%-át, de legfeljebb 25%-ot engednek el. Írjunk most egy programot, amit meghívhatunk az éves jövedelemmel és a gyerekek számával és az megmondja az adónkat! Emlékezzünk a 3. lecke Negativ programjára, hogyan értékeltük ki ott a paramétereket! Lebegõpontos számot még nem értékeltünk ki, ezért leshetsz egy kicsit a megoldásban. A programunkban igyekezzünk olyan függvényt írni, ami a leginkább lerövidíti a programot! Íme a megoldás, de csak a paraméterek kiértékelését lesheted ki belõle, a többit neked kell megoldanod!