A InfoWiki wikiből
(Új oldal, tartalma: „<cim cim3="Véletlenszám előállítás" cim2="Magasszintű Programozási Nyelvek I." cim1="Imperatív, procedurális nyelvek alapjai" prev="mp1/page200" next="mp...”) |
Aktuális változat (2009. október 15., 09:44) (lapforrás) |
||
11. sor: | 11. sor: | ||
<path p1="Kezdolap|Kezdőlap" p2="EBooks|Jegyzetek" p3="mp1/Nyitolap|Tartalomjegyzék" | <path p1="Kezdolap|Kezdőlap" p2="EBooks|Jegyzetek" p3="mp1/Nyitolap|Tartalomjegyzék" | ||
xx="-" | xx="-" | ||
- | w1="mp2 | + | w1="mp2/Nyitolap|Gyakorlatok" w2="mp1/Tematika|Vizsgatematika" w3="cs/Blog|Programok C# nyelven" |
/> | /> | ||
Aktuális változat
Véletlenszám előállítás
Véletlen értékekre gyakran van szükség programokban. Egyszerűbb esetekben mesterséges intelligenciát helyettesíthet (sakkprogramokban mondjuk mókás ha a következő lépést a számítógép véletlenszerűen sorsolja ki). A mi esetünkben tesztelési segítség lesz. Tömbök, nagy mennyiségű számbekérés esetén szimulációs, tesztelési célokra is használjuk a véletlenszámokat. Ezt esetben például nem bekérünk 100 darab számot, hanem előállítunk 100 darab számot. A program további részei ekkor a generált számokkal ugyanúgy működhetnek, mint a bekértekkel - a tesztelés folytatható. A hiba felderítése és javítása utáni újraindításkor a 100 szám újra generálásra kerül, nem veszítünk el rengeteg időt az újra beírással.
Hatékony módszer a fájlból olvasás is, de a véletlenszám előállításnak van egy vitathatatlan előnye: minden futásnál más-más számokat kaphatunk, így a tesztelés szélsőségesebb körülmények között is megvalósítható.
A véletlenszám előállítás automatizált, a programozónak csak kérnie kell a következő véletlen számot - és megkapja. Ugyanakkor fontos tudni néhány dolgot a háttérbeli működésről, mivel látni fogjuk, sok működési problémára kaphatunk úgy magyarázatot.
Amit mi véletlen számnak hívunk - először is tudni kell hogy nem véletlen szám. Egy kiinduló értékből állítja elő egy algoritmus. Az algoritmus numerikus műveleteket végez a kiinduló értéken (műveletsorozat). Vagyis a kiinduló érték ismeretében az új érték előre kiszámítható (megjósolható). Az új véletlen érték egyúttal megjegyzésre is kerül, így a következő véletlen érték előállítás alapjául is fog szolgálni. Vagyis a kezdő kiinduló érték nem csak az első véletlenszám előállítás meghatározó eleme, hanem az összes többinek is.
A véletlenszámok előállításához egy Random típusú változóra van szükség. A változó neve legyen esetünkben rnd (de más név is választható). Ezen változóba speciális kezdőértéket kell elhelyezni:
Random rnd = new Random();
Megjegyzés: a fenti értékadás során a Random osztályt példányosítjuk. De az OOP fogalmak csak következő félévben alakulnak ki.
Véltelen egész szám
A fenti rnd változó segítségével képezhetünk véletlen számokat. Ehhez a Next() függvényt kell meghívni:
Random rnd = new Random(); int x = rnd.Next(10,20);
A fenti esetben a Next(10,20) egy olyan váletlen számot generál, amely a [10,20) intervallumba esik. Ha alaposan megvizsgáljuk ezt az intervallum-felírást, láthatjuk, hogy balról zárt, jobbról nyitot. Vagyis az előállított érték lehet 10,11,12,...,19, de a 20 érték nincs benne. Másképpen felírva 10<= x < 20 lesz az eredmény. Amennyiben maga a 20 érték is kellene, akkor rnd.Next(10,21) felírás szükséges.
Ha újabb véletlen számra lenne szükségünk, ugyanazon rnd változót tudjuk használni:
Random rnd = new Random(); int x = rnd.Next(10,20); int y = rnd.Next(100,150); int z = rnd.Next(3,9);
Egyparaméteres next
Lehetőség van arra, hogy a Next() függvényt csak egyetlen paraméterrel használjuk:
int a = rnd.Next(10);
Az a változó ebben az esetben a [0,10) intervallumból kap értéket (0 <= a < 10). Vagyis az egyparaméteres változat esete visszavezethető a kétparaméteresre, ahol az első paraméter értéke 0.
Tört véletlen érték osztással
Amennyiben nem egész, hanem tört értékre van szükségünk - két módszer közül választhatunk.
Első módszer szerint előállítunk egy egész értéket, majd osztási művelettel képezzük a tört számot:
int a = rnd.Next(10); double d = a/4.0;
Ebben a példában a d értéke [0,2.5) közé fog esni. De mivel 4-el osztunk, ezek a tört számok legfeljebb 1 tizedesjegyet tartalmaznak. Ezen persze lehet segíteni könnyedén:
int a = rnd.Next(100); double d = a/40.0;
Tovább finomítva:
int a = rnd.Next(1000); double d = a/400.0;
Egyszerűbben is hozzáfoghatunk: amennyiben [1,5) közé eső, maximum 3 tizedesjegyet tartalmazó értékre van szükségünk:
int a = rnd.Next(100,500); double d = a/100.0;
Tört véletlen érték szorzással
A másik módszer szerint eleve tört számot képezünk. Erre a NextDouble() függvény alkalmazható:
double d = rnd.NextDouble();
A NextDouble() paraméter nélküli változatban áll csak rendelkezésünkre, így nem szabályozható szépen a kapott eredmény. Az minden esetben a [0,1) intervallumból (0<=d<1) kerül majd ki, és double típushoz illően akár 15 számjegyből is állhat.
Amennyiben nem ilyen intervallumbeli értékre van szükségünk, úgy szorozni kell:
double f = rnd.NextDouble(); double d = f*5;
Ha az értéket szorozzuk 5-el, akkor a [0,5) intervallumba tesszük át a generált véletlen értékeket (amelyek továbbra is akár 15 tört számjegyet is tartalmaznak.
double f = rnd.NextDouble(); double d = f*8+2;
A fenti képlet szerint a d értéke [2,10) közé eshet. Ezt egyszerű kiszámolni az alábbi elvek szerint:
- az f értéke maximum 0.99999999 lehet (közel 1.0), mely esetben a fenti képlet 9.99999999 közeli értéket ad, vagyis d 1értéke közelíti a 10-et, de sosem éri el.
- az f értéke minimum 0.0, amely esetben a fenti képlet 2.0-t ad meg.
Kerekítés
Amennyiben szorzással állítjuk elő a tört értéket, nagyon sok tizedesjegy kerülhet bele a generált számba. Ha ezt szabályozni szeretnénk, akkor kerekítést kell alkalmazni. Ennek során felszorozzuk a kapott tört számot megfelelően, egész számmá alakítjuk, majd az osztás segítségével visszaalakítjuk tört értékké:
double f = rnd.NextDouble(); double d = (int)(f*100)/100.0;
Az f*100 során az értékünk a [0,100) intervallumbeli tört értékké alakul. A típuskonverzió miatt átalakul egész számmá a [0,100) intervallumban, majd az osztás miatt visszaalakul tört értékké a [0,1) intervallumba, de csak maximum 2 tizedesjegyet fog tartalmazni.
Ez a módszer persze semmiben nem különbözik az elsőtől, amikor is eleve egész számot képzünk:
int a = rnd.Next(0,100); double d = a/100.0;