fel
le

Véletlenszám előállítása

A számítógépes programok működésük során nagyon sok adattal dolgoznak. Ezek különböző helyekről szárzamhatnak:

  • külső adattárból, adatbázisból
  • program működése közbeni adatbevitel (billentyűzet, egér)
  • generált véletlen számok

Utóbbiak (a generált véletlen számok) gyakran kerülnek használatba játékprogramokban, oktatóprogramokban. Ezen felül komolyabb feldolgozó algoritmusok is használnak véletlen számokat döntéshelyzetekben.

A programozás tanulás során a véletlenszámokat a billentyűzetről történő adatbevitel helyettesítésére használjuk. Ezzel a program futtatását, kipróbálását, tesztelését könnyítjük meg. Amennyiben a programunk sok adatot kérne be - a billentyűzetes adatbeírásokat kiválthatjuk generált véletlen számokkal. A programunk további részei úgy dolgoznak a generált értékekkel, mintha azokat a program kezelője írta volna be.

A véletlenszámok előállításához szükség van egy speciális típusú változóra, melyet a következőképpen kell deklarálni és feltölteni értékkel:

Random rnd = new Random();
 

A változónkat esetünkben rnd-nek nevezzük - ezt a nevet tetszőleges választhatjuk meg. Az rnd típusa Random. Ez egy objektumosztály típus, melyből készített változókat példányoknak hívjuk, és speciális módon kell értéket elhelyezni bennük. A new kulcsszóval kell memóriát foglalni, majd meghívni a konstruktor függvényt. Nem baj, ha ez ezen a ponton még nem világos, egyelőre elég ha megjegyezzük hogyan kell ezt csinálni. Ne felejtsük el a new Random() oldalon a két gömbölyű zárójel is fontos!

// két sorban írva
Random rnd;
rnd = new Random();

// egyetlen sorban
Random rnd = new Random();
 
A Random rnd = new Random() módon deklarált és értékkel feltöltött rnd változó segítségével lehet véletlen számokat előállítani. Egyetlen ilyen rnd változó tetszőlegesen sok véletlen szám e lőállítására képes.

Amennyiben az rnd változónk a fentiek szerint rendelkezésünkre áll - megkérhetjük hogy állítson elő nekünk véletlen számokat. Elsősorban egész számokat szoktunk vele előállítani, de később látunk példát tört számok előálítására is.

Egész számok generálása

Az rnd változó Next(...) függvényével lehet a következő véletlen számot lekérni. A next-nek meg kell adni, mekkora véletlen számokat kérünk. Ezt egy intervallum formájában kell megadni, vagyis le kell írni, mi lehet a legkisebb és legnagyobb véletlen szám, amit a next előállíthat. Sajnos, a next ezt furcsán értelmezi. A Next(10,40) úgy értelmezi, hogy az előállított véletlen számnak 10 és 40 közé kell esnie, oly módon, hogy lehet 10,11,12,13,...,38,39. Vagyis bár 10 lehet, de 40 nem lehet! Ezt a matematikusok úgy fogalmazzák, hogy a véletlen szám a [10,40) balról zárt, jobbról nyitott intervallumba esik.

Az rnd.Next(10,40) a [10,40) balról zárt, jobbról nyitott intervallumból állít elő véletlen számot, vagyis az előállított szám a 10,11,12,...,38,39 egész számok valamelyike lesz. Ha [10,40] intervallum kell, ahol maga a 40 is szükséges, akkor rnd.Next(10,41) formát kell használni. Általában fogalmazva valamely [A,B] intervallumbeli egész szám előállításához az rnd.Next(A,B+1) formát kell használni!

Ezek alapján az alábbi adatbekérő kód helyettesíthető véletlen számmal:

// ez a bekérés
Console.Write("Írj be az életkorod:");
int ev = int.Parse( Console.ReadLine() );
// erre cserélhető
int ev = rnd.Next(14,90);
Console.Write("Az életkorod:{0}",ev);
 
Mindíg ügyeljünk arra, hogy a next balról zárt, jobbról nyitott intervallumban gondolkodik. Vagyis az rnd.Next(1,2) csak magát az 1 értéket képes előállítani. Ha lottószámokat akarunk kapni, akkor az rnd.Next(1,91) kell írni. Ha érdemjegyet, akkor rnd.Next(1,6).

A next-nek van olyan változata, ahol csak egyetlen (felső) értéket kell megadni. Ez esetben az alsó érték automatikusan a nulla. Az rnd.Next(10) nem más, mint az rnd.Next(0,10). Ezt a formát gyakran használjuk majd vektor vagy listán belüli index generálására. Ugyanis egy N elemű lista vagy vektor elemeinek sorszámozása 0-tól indul, az utolsó sorszám épp N-1, vagyis a [0,N) intervallumba esik. Ekkor az rnd.Next(N) éppen jó számokat fog generálni!

A next segítségével negatív véletlen számok is előállíthatóak, noha erre ritkábban van szükség. Az rnd.Next(-10,10) olyan számokat állít elő, amelyek a [-10,10) intervallumba esnek, vagyis a -10,-9,-8,...,-1,0,1,2,...,9 számok valamelyikét.

Tört számok előállítása

A next segítségével csak egész számok előállítására van lehetőség. Ez önmagában nem akadály, mivel az osztás segítségével a tört számok már képezhetőek. Tegyük fel, hogy 5 és 8 közötti tört számokat akarunk kapni. Fix értékkel fogunk osztani, legyen ez a (kissé értelmetlenül) a 78. Ekkor legalább 5*78=390, és maximum 8*78=624 számokat kell előáttani, vagyis rnd.Next(390,624)/78.0 -t kell írni. Figyelem! Nem 78-al, hanem 78.0 -val osztunk. Ugyanis az rnd.Next(..) is egész szám (int), a 78 is egész (int), ilyenkor az osztás művelet egész osztás lenne, vagyis az rnd.Next(390,624)/78 csak az 5,6,7 értékek valamelyik lenne!

Jellemzően nem szoktunk ilyen bonyolult számmal osztani. Vagy 10-el, vagy 100-al (vagy egyéb 10 hatvánnyal) osztunk. Ez esetben egyszerűbb a kalkuláció: rnd.Next(50,80)/10.0. Vegyük azonban észre, hogy ez csak 5.0, 5.1, ..., 7.9 lehet, magát a 8.0 -t nem kaphatjuk meg. Belátható, hogy ezen esetünkben az rnd.Next(50,81)/10.0 módon lehet segíteni, hiszen ez [50,81) intervallumból vesz ki számokat, ez lehet 50,51,52,...,79,80 valamelyike. Ha ezeket osztjuk 10-el, akkor 5.0, 5.1, ..., 7.9, 8.0 számokat kapunk.

Ha két tizedesjegyes tört számokat szeretnénk, akkor 100.0-val kell osztani. Ez esetben az rnd.Next(500,801)/100.0 módon lehet [5.0,8.0] közötti tört számokat kapni.

NextDouble() használata

Másik mód, amellyel tört számokat lehet előállítani, a NextDouble() használata. Ez kicsit más, mint a Next(...), nem szükséges számára megadni az előállítandó tört szám milyen alsó-felső intervallumból kerüljön ki. A NextDouble mindíg a [0,1) intervallumból állít elő tört értéket. Odafigyelve láthatjuk, hogy a 0.0 -t elő tudja állítani, a 0.9999999999 is, de az 1.0-t már nem.

Az rnd.NextDouble() nem vár paramétert, minden esetben a [0,1) balról zárt, jobbról nyitott intervallumból generál tört számot. Ezen tört szám double típusú, vagyis maximum 15 számjegyből álló tört számot kaphatunk.

Amennyiben nekünk nem az alapértelmezett [0,1) intervallumbeli tört érték kell, úgy a megkapott értéket manipulálnunk kell. Például az [5,8) intervallumhoz rnd.NextDouble()*3+5 forma kell. Amennyiben a NextDouble épp a 0.0-t állítaná elő, ez a numerikus kifejezés a 0.0*3+5=5.0 értéket állítja elő. Ha a NextDouble a maximális 0.9999999-t generálná, úgy ez a kifejezés a 0.9999999*3+5=7.99999999 értéket állítaná elő, tehát rendben vagyunk.

A NextDouble segítségével valamely [A,B) intervallumbeli tört számot úgy állítunk elő, hogy rnd.NextDouble()*(B-A)+A képletet használjuk. Törődjünk bele, hogy [A,B] zárt intervallumbeli tört szám előállítása ezzel a módszerrel nem működik.
Hernyák Zoltán
2013-01-24 10:41:50