Java programozás 11. – Véletlen számok

Véletlen számok, avagy bízzuk a sorsra

Programozás során sokszor előfordul, hogy valamilyen értéket véletlenszerűen kell megadni, vagy fel kell tölteni egy tömböt véletlen számokkal. A véletlen szám generálásának módszere a következő:

Először meg kell határozni annak az intervallumnak a határait, amelyből az adott számot sorsolni kell:

[0;20]
[10;30]
[-10;10]
[-20;0]
[-40;-20]

Ha egész számokat akarunk sorsolni, akkor ezek a típusok jöhetnek szóba. A jó az egészben az, hogy bármilyen egészeket tartalmazó intervallumra egy általános “képlettel” meg lehet adni a sorsolandó számot. Először meg kell határozni az intervallum alsó és felső határát. Ha ezeket tudjuk, akkor jöhet a sorsolást végző programkód. Ennek általános formája a következő:

(int)( Math.random()*(felső-alsó+1) )+alsó;

Bontsuk akkor részekre ezt a kódot. Kezdjük belülről kifelé haladva:

A Math.random() függvény egy véletlen számokat generáló függvény, mely egy lebegőpontos számot (nem egész) sorsol ki a [0;1[ intervallumból. Nem rontottam el az intervallum zárójelét, ez ugye azt jelenti, hogy a kisorsolt érték legkisebb értéke nulla, a legnagyobb viszont mindenképpen 1-nél kisebb lesz. Így is írhattam volna, hogy a Math.random() függvény ilyen értékeket sorsol: 0 <= szám < 1

Ezt a számot meg kell szorozni az intervallum méretével, amit minden esetben úgy kapunk, hogy a felső határból kivonjuk az alsót és 1-et hozzáadunk. Az egyik példánál maradva a [0;10] intervallum mérete 11, hiszen 10-0+1 = 11. Miért adunk hozzá egyet? Mert ha csak a két szám különbségét vennénk, akkor az intervallumba a felső határ nem tartozna bele. Miért? Ha emlékszel, a Math.random() 1-et sosem sorsol, ezért az egyik alul részletezett lépés miatt a felső határ kimaradna. Ha ezt az intervallum méretet behelyettesítjük a megfelelő helyre egyszerűsödik a képlet:

(int)(Math.random() * intervallum_mérete) + alsó;

Ha most nézzük a belső részt, akkor alakul a dolog. Nézzük újra a példákat immár behelyettesítve az eddig tanultakat:

[0;20]     (int)(Math.random() * 21) + alsó;
[10;30]    (int)(Math.random() * 21) + alsó;
[-10;10]   (int)(Math.random() * 21) + alsó;
[-20;0]    (int)(Math.random() * 21) + alsó;
[-40;-20]  (int)(Math.random() * 21) + alsó;

Érdekes módon habár 5 különféle típust adtam meg intervallumra, az intervallumok mérete mégis egyforma. Nincs ezzel semmi gond, mert a véletlen szám sorsolás első lépése a megfelelő méretű sorsolási intervallum meghatározása, ami ismétlésképp: felső – alsó + 1

Ha ez megvan, akkor már csak ezt a megfelelő méretű intervallumot kell eltolni a számegyenesen a megfelelő irányba úgy, hogy az intervallum alsó határa a megfelelő kezdőpontban legyen. Ez pusztán csak annyit jelent, hogy a zárójelben lévő részhez a zárójelen kívül – hozzáadom az intervallum alsó határát (ami negatív érték esetén természetesen kivonást jelent). Lássuk így a megoldásokat:

[0;20]     (int)(Math.random() * 21); // a nullát nem adom hozzá
[10;30]    (int)(Math.random() * 21) + 10;
[-10;10]   (int)(Math.random() * 21) - 10;
[-20;0]    (int)(Math.random() * 21) - 20;
[-40;-20]  (int)(Math.random() * 21) - 40;

Ezzel már majdnem készen is vagyunk, de még ott van egy fura rész a kód elején: (int) Ez az úgynevezett típuskényszerítés, angolul typecast. Ez azt jelenti, hogy a közvetlenül utána szereplő értéknek közvetlenül megmondja, hogy milyen típusa legyen. A Math.random(), ha emlékszel, egy lebegőpontos (valós) számot sorsolt, ami nem egész, de az intervallum egész számokat kell, hogy tartalmazzon. Ezzel megadtuk, hogy az (int) után lévő szám legyen egész, ami valójában azt jelenti, hogy levágjuk a tizedesjegyeket.

(int)(Math.random() * 21) - 20;

Így lesz az intervallum mérete egész szám, hiszen eredetileg a [0;21[ intervallumból bármilyen valós szám lehetett volna.

Fontos még megjegyeznem, hogy az intervallum eltolásakor az alsó határ hozzáadását mindenképp úgy adjuk meg, ahogy a példában látjuk. Több helyen ilyen megoldással találkoztam, amik rosszak:

(int)(Math.random() * 21 - 40);

Ez a megoldás azért rossz, mert a csonkolás és az intervallum negatív tartományba tolása miatt az alsó határ (a példában a -20) sosem szerepelhet a sorsolásban. Ennek a valódi oka egyébként az, hogy a Math.random() 1-et sosem sorsolhat, így a csonkolás miatt a negatív számoknál gond lesz a legnagyobb (valójában legkisebb) értékkel. Ha valaki nem hiszi, számoljon utána.

Végül álljon itt pár feladat adott intervallumból történő sorsolás gyakorlásához:

[-55;15]   [-40;5]   [60;105]   [-50;35]   [45;95]   [50;50]   [10;25]   [20;105]   [80;95] [-30;-25]   [40;60]   [-20;45]   [-10;15]   [-20;25]   [-45;-20]   [-25;75]   [-20;15]   [-15;95]

Következő lecke: Ciklusok

3 Replies to “Java programozás 11. – Véletlen számok”

  1. Pingback: Java programozás 9. – Feltételvizsgálatok

Vélemény, hozzászólás?

Az e-mail címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük

*

Ez az oldal az Akismet szolgáltatást használja a spam csökkentésére. Ismerje meg a hozzászólás adatainak feldolgozását .