1. Álvéletlen számok

Néha a programozónak látszólag egyszerű feladatokkal kell szembenéznie: "válasszon ki egy véletlenszerű filmet egy bizonyos listáról", "válasszon egy lottó nyertest", "keverje össze a lejátszási listát, amikor a felhasználó megrázza az okostelefonját", "válasszon egy véletlen számot az üzenet titkosításához". , stb. A fejlesztő minden esetben feltesz egy logikus kérdést: hogyan lehet véletlen számot kapni?

Valójában egy igazán véletlen számot meglehetősen nehéz megtenni. Valójában ez olyan nehéz, hogy egyes számítógépekbe speciális matematikai koprocesszorokat építenek be, hogy olyan számokat állítsanak elő, amelyek megfelelnek a valódi véletlenszerűség minden követelményének.

A programozók saját megoldást találtak ki: pszeudovéletlen számok . Az álvéletlen számok egyfajta sorozat, amelynek számai véletlenszerűnek tűnnek. A gondos elemzés elvégzésével azonban a szakértő bizonyos mintákat találhat a sorozatban. Az ilyen számok nem alkalmasak titkos dokumentumok titkosítására, de a játékban a kockadobás szimulálására elegendőek.

Számos algoritmus létezik álvéletlen számsorozat generálására. Szinte mindegyik generálja a következő véletlenszámot az előző szám és néhány további segédszám alapján.

Például ez a program 1000nem ismétlődő számokat jelenít meg:

public class Main
{
   public static int a = 41;
   public static int c = 11119;
   public static int m = 11113;
   public static int seed = 1;

   public static int getNextRandom()
   {
     seed = (a * seed + c) % m;
     return seed;
   }

   public static void main(String[] args)
   {
     for (int i = 0; i < 1000; i++)
     {
       System.out.println(getNextRandom());
     }
   }
}

Egyébként itt nem álvéletlen számokról beszélünk. Pszeudovéletlen számsorozatról beszélünk. Egyetlen számra nézve lehetetlen megmondani, hogy véletlenszerű-e vagy sem.

Valójában többféle módon lehet véletlen számot szerezni:

public static int getRandomNumber()
{
   return 4; // Here's a random number (we got it by rolling a die)
}

2.Math.random()

Java-ban az Mathosztálynak van egy speciális metódusa, amely véletlen számot ad vissza. És ahogy sejtheti, a módszer neve random. Általában a következőképpen néz ki ennek a módszernek a neve:

Math.random()

Ez a metódus nem vesz fel paramétereket, és pszeudovéletlen valós számot ad vissza a 0-tól ig terjedő tartományban 1. Maga az 1-es szám nem szerepel a tartományban.

Példa:

Kód Konzol kimenet
public class Main
{
   public static void main(String[] args)
   {
     for (int i = 0; i < 10; i++)
     {
       System.out.println(Math.random());
     }
   }
}
0.9703753971734451
0.09979423801773157
0.994048474709053
0.2852203204171295
0.13551248551226025
0.3128547131272822
0.5342480554101412
0.6817369932044817
0.1840767788961758
0.06969563435451254

De mi van, ha ez a módszer nem egészen az, amire szüksége van? Tegyük fel, hogy olyan programot akarunk írni, amely egy hatoldalú kocka dobását szimulálja. Hogyan kaphatunk véletlenszerű egész számokat az 1..6 tartományban a 0..1 tartományba eső valós számok helyett?

Valójában nagyon egyszerű.

Először is le kell képeznie a tartományt [0, 1)a következőre [0, 6). Ehhez egyszerűen szorozza meg a visszaadott eredményt random()-val 6. Természetesen, hogy egész számokat kapjunk, fel kell kerekíteni:

Kód Konzol kimenet
public class Main
{
   public static int getRandomDieNumber()
   {
      return (int) (Math.random() * 6);
   }

   public static void main(String[] args)
   {
      for (int i = 0; i < 10; i++)
      {
         int x = getRandomDieNumber();
         System.out.println(x);
      }
   }
}
5
2
3
3
2
4
1
1
5
0

A tartomány egy getRandomDieNumber()véletlenszerű egész számot ad vissza 0..5. De ez nem lesz szám a készletben 1, 2, 3, 4, 5, 6. Ez egy szám lesz a készletben 0, 1, 2, 3, 4, 5.

Ha számokra van szüksége a készletben 1, 2, 3, 4, 5, 6, akkor csak adjon hozzá egyet a véletlenszerű számokhoz:

Kód Konzol kimenet
public class Main
{
   public static int getRandomDieNumber()
   {
      return (int) (Math.random() * 6) + 1;
   }

   public static void main(String[] args)
   {
     for (int i = 0; i < 10; i++)
     {
       int x = getRandomDieNumber();
       System.out.println(x);
     }
   }
}
3
2
1
3
6
5
6
1
6
6

Ez most tökéletes!



3. Randomosztály

A Java-nak van egy speciális Randomosztálya, amely pszeudovéletlen számok sorozatát tartalmazza. Az osztályból több objektumot is létrehozhat Random. Ezen objektumok mindegyike létrehoz egy saját pszeudovéletlen számsorozatot.

Ez egy szuper érdekes óra sok érdekes módszerrel. Kezdjük a legegyszerűbbel.

double nextDouble()

0.0Ez a módszer egy véletlenszerű valós számot ad vissza a - tartományban 1.0. Nagyon hasonlít a módszerhez Math.random(). És nem csoda, hiszen a Math.random()metódus egyszerűen meghívja a nextDouble()metódust egy Randomobjektumon.

float nextFloat()

Ez a metódus nagyon hasonlít a nextDouble()metódushoz, de a visszaadott véletlen szám egy float. 0.0Szintén a - tartományba esik 1.0. És mint mindig a Java-ban, a tartomány nem tartalmazza 1.0magát a számot.

Random r = new Random();
float f = r.nextFloat();

int nextInt(int max)

Ez a metódus egy véletlenszerű egész számot ad vissza a tartományban [0, max). 0benne van a kínálatban, de maxnem.

Más szóval, ha véletlen számot szeretne kapni a halmazban 1, 2, 3, 4, 5, 6, akkor hozzá kell adnia egyet a visszaadott véletlen számhoz:

Random r = new Random();
int x = r.nextInt(6) + 1;

int nextInt()

Ez a módszer hasonló az előzőhöz, de nem igényel paramétereket. Tehát mi a visszatérési értékeinek tartománya? -tól -2 billion-ig +2 billion.

Nos, hogy pontos legyek, tól -2147483648-ig +2147483647.

long nextLong()

Ez a metódus hasonló a nextInt()metódushoz, de a visszatérési érték valahol az s teljes lehetséges tartományába esik long.

boolean nextBoolean()

Ez a metódus véletlenszerű booleanértéket ad vissza: falsevagy true. Ez nagyon kényelmes, ha véletlenszerű logikai értékek hosszú sorozatát kell beszereznie.

void nextBytes(byte[] data)

Ez a metódus nem ad vissza semmit (mivel a visszatérési típus void). Ehelyett véletlenszerű értékekkel tölti fel az átadott tömböt. Ez nagyon hasznos, ha nagy, véletlenszerű adatokkal teli pufferre van szüksége.

double nextGaussian()

0.0Ez a módszer egy véletlenszerű valós számot ad vissza a - tartományban 1.0. A számok azonban nem egyenletesen oszlanak el ebben a tartományban. Ehelyett normál eloszlást követnek .

A tartomány közepéhez közeli értékek ( 0.5) gyakrabban fordulnak elő, mint a tartomány végén lévő értékek.

Véletlen osztály

Esetünkben az értékeloszlás csúcsa a0.5