Személyes eszközök
Keresés

 

A InfoWiki wikiből


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;
Az osztásnál ügyeljünk, hogy ne 100-al osszunk, hanem 100.0-al, amely alakja miatt double típusú literálnak minősül. Ha egész típusú literállal osztunk egy egész számot, annak eredménye is egész szám lesz, tehát a a/100 eredménye esetünkben egy [1,5) közé eső egész szám lenne!


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;


Hernyák Zoltán
A lap eredeti címe: „http://wiki.ektf.hu/wiki/Mp1/page210
Nézetek
nincs sb_3.239.109.55 cikk