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:
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!
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.
Ezek alapján az alábbi adatbekérő kód helyettesíthető véletlen számmal:
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);
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.
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.