1. Numerele pseudo-aleatorie

Uneori, un programator se confruntă cu sarcini aparent simple: „selectează un film aleatoriu dintr-o anumită listă”, „alege un câștigător la loterie”, „se amestecă lista de redare când utilizatorul își scutură smartphone-ul”, „alege un număr aleatoriu pentru a cripta un mesaj” , etc. În fiecare caz, dezvoltatorul pune o întrebare logică: cum să obțineți un număr aleatoriu?

De fapt, obținerea unui număr cu adevărat aleatoriu este destul de dificil de făcut. De fapt, este atât de dificil încât în ​​unele computere sunt încorporate coprocesoare matematice speciale pentru a genera numere care să îndeplinească toate cerințele pentru adevărata aleatorie.

Programatorii au venit cu propria lor soluție: numere pseudoaleatoare . Numerele pseudo-aleatorie sunt un fel de succesiune, ale cărei numere par a fi aleatoare. Cu toate acestea, efectuând o analiză atentă, un expert poate găsi anumite modele în secvență. Astfel de numere nu sunt potrivite pentru criptarea documentelor secrete, dar sunt suficiente pentru a simula aruncarea unui zar într-un joc.

Există mulți algoritmi pentru generarea unei secvențe de numere pseudoaleatoare. Aproape toate generează următorul număr aleatoriu pe baza numărului anterior și a unor numere auxiliare suplimentare.

De exemplu, acest program va afișa 1000numere care nu se repetă:

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());
     }
   }
}

Apropo, aici nu vorbim de numere pseudoaleatoare. Vorbim despre o succesiune de numere pseudoaleatoare. Privind un singur număr, este imposibil să spunem dacă este aleatoriu sau nu.

Într-adevăr, există mai multe moduri de a obține un număr aleatoriu:

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

2.Math.random()

În Java, Mathclasa are o metodă specială care returnează un număr aleator. Și după cum ați putea ghici, metoda se numește random. În general, iată cum arată să numim această metodă:

Math.random()

Această metodă nu ia parametri și returnează un număr real pseudoaleator în intervalul de la 0până la 1. Numărul 1 în sine nu este inclus în interval.

Exemplu:

Cod Ieșire de consolă
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

Dar dacă această metodă nu este exact ceea ce aveți nevoie? Să presupunem că doriți să scrieți un program care simulează lansarea unui zar cu șase fețe. Cum obții numere întregi aleatorii în intervalul 1..6, în loc de numere reale din intervalul 0..1?

De fapt, este destul de simplu.

În primul rând, trebuie să mapați intervalul [0, 1)pe [0, 6). Pentru a face acest lucru, pur și simplu înmulțiți rezultatul returnat random()cu 6. Desigur, pentru a obține numere întregi, trebuie să rotunjiți:

Cod Ieșire de consolă
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

Returnează getRandomDieNumber()un număr întreg aleatoriu în interval 0..5inclusiv. Dar nu va fi un număr în set 1, 2, 3, 4, 5, 6. Va fi un număr din set 0, 1, 2, 3, 4, 5.

Dacă ceea ce aveți nevoie sunt numerele din set 1, 2, 3, 4, 5, 6, adăugați doar unul la numerele aleatorii:

Cod Ieșire de consolă
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

Acum e perfect!



3. Randomclasa

Java are o clasă specială Randomcare încapsulează o secvență de numere pseudoaleatoare. Puteți crea mai multe obiecte ale Randomclasei. Fiecare dintre aceste obiecte va genera propria sa secvență de numere pseudoaleatoare.

Aceasta este o clasă super interesantă, cu o mulțime de metode interesante. Să începem cu cel mai simplu.

double nextDouble()

Această metodă returnează un număr real aleatoriu în intervalul 0.0- 1.0. Este foarte asemănător cu Math.random()metoda. Și nu e de mirare, deoarece Math.random()metoda apelează pur și simplu nextDouble()metoda pe un Randomobiect.

float nextFloat()

Această metodă este foarte asemănătoare cu nextDouble()metoda, dar numărul aleator returnat este un float. De asemenea, se află în intervalul 0.0- 1.0. Și, ca întotdeauna în Java, intervalul nu include numărul 1.0în sine.

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

int nextInt(int max)

Această metodă returnează un număr întreg aleatoriu în intervalul [0, max). 0este inclus în gamă, dar maxnu este.

Cu alte cuvinte, dacă doriți să obțineți un număr aleator în set 1, 2, 3, 4, 5, 6, atunci trebuie să adăugați unul la numărul aleator returnat:

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

int nextInt()

Această metodă este similară cu cea anterioară, dar nu ia niciun parametru. Deci, care este intervalul pentru valorile sale returnate? De la -2 billionpână la +2 billion.

Ei bine, mai precis, de la -2147483648până la +2147483647.

long nextLong()

Această metodă este similară cu nextInt()metoda, dar valoarea returnată va cădea undeva în întregul interval posibil de longs.

boolean nextBoolean()

Această metodă returnează o booleanvaloare aleatorie: falsesau true. Acest lucru este foarte convenabil atunci când trebuie să obțineți o secvență lungă de valori booleene aleatoare.

void nextBytes(byte[] data)

Această metodă nu returnează nimic (deoarece tipul de returnare este void). În schimb, umple matricea transmisă cu valori aleatorii. Acest lucru este foarte util atunci când aveți nevoie de un buffer mare plin cu date aleatorii.

double nextGaussian()

Această metodă returnează un număr real aleatoriu în intervalul 0.0- 1.0. Cu toate acestea, numerele nu sunt distribuite uniform în acest interval. În schimb, ele urmează o distribuție normală .

Valorile aproape de mijlocul intervalului ( 0.5) vor apărea mai des decât valorile de la sfârșitul intervalului.

Clasa aleatorie

În cazul nostru, vârful distribuției valorii va fi la0.5