1. Numeri pseudocasuali

A volte un programmatore deve affrontare compiti apparentemente semplici: "selezionare un film a caso da un determinato elenco", "scegliere un vincitore della lotteria", "mescolare la playlist quando l'utente scuote lo smartphone", "scegliere un numero a caso per crittografare un messaggio" , ecc. In ogni caso, lo sviluppatore pone una domanda logica: come ottenere un numero casuale?

In realtà, ottenere un numero veramente casuale è piuttosto difficile. In effetti, è così difficile che speciali coprocessori matematici siano incorporati in alcuni computer per generare numeri che soddisfino tutti i requisiti per una vera casualità.

I programmatori hanno trovato la loro soluzione: i numeri pseudocasuali . I numeri pseudocasuali sono un tipo di sequenza i cui numeri sembrano essere casuali. Tuttavia, eseguendo un'attenta analisi, un esperto può trovare determinati schemi nella sequenza. Tali numeri non sono adatti per cifrare documenti segreti, ma sono sufficienti per simulare il lancio di un dado in un gioco.

Esistono molti algoritmi per generare una sequenza di numeri pseudocasuali. Quasi tutti generano il numero casuale successivo in base al numero precedente e alcuni numeri ausiliari aggiuntivi.

Ad esempio, questo programma visualizzerà 1000numeri non ripetitivi:

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

A proposito, qui non stiamo parlando di numeri pseudocasuali. Stiamo parlando di una sequenza di numeri pseudocasuali. Guardando un singolo numero, è impossibile dire se sia casuale o meno.

In effetti, ci sono vari modi per ottenere un numero casuale:

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

2.Math.random()

In Java, la Mathclasse ha un metodo speciale che restituisce un numero casuale. E come puoi immaginare, il metodo si chiama random. In generale, ecco come sembra chiamare questo metodo:

Math.random()

Questo metodo non accetta parametri e restituisce un numero reale pseudocasuale nell'intervallo da 0a 1. Il numero 1 stesso non è incluso nell'intervallo.

Esempio:

Codice Uscita console
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

Ma cosa succede se questo metodo non è proprio quello di cui hai bisogno? Supponiamo di voler scrivere un programma che simuli il lancio di un dado a sei facce. Come si ottengono numeri interi casuali nell'intervallo 1..6, invece di numeri reali nell'intervallo 0..1?

In realtà è piuttosto semplice.

Innanzitutto, devi mappare l'intervallo [0, 1)su [0, 6). Per farlo basta moltiplicare il risultato restituito da random()per 6. Naturalmente, per ottenere numeri interi, è necessario arrotondare:

Codice Uscita console
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

Il getRandomDieNumber()restituisce un numero intero casuale nell'intervallo 0..5compreso. Ma non sarà un numero nel set 1, 2, 3, 4, 5, 6. Sarà un numero nel set 0, 1, 2, 3, 4, 5.

Se ciò di cui hai bisogno sono i numeri nel set 1, 2, 3, 4, 5, 6, aggiungine uno ai numeri casuali:

Codice Uscita console
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

Adesso è perfetto!



3. Randomclasse

Java ha una Randomclasse speciale che incapsula una sequenza di numeri pseudocasuali. È possibile creare diversi oggetti della Randomclasse. Ciascuno di questi oggetti genererà la propria sequenza di numeri pseudocasuali.

Questa è una classe super interessante con molti metodi interessanti. Iniziamo con il più semplice.

double nextDouble()

Questo metodo restituisce un numero reale casuale nell'intervallo 0.0- 1.0. È molto simile al Math.random()metodo. E non c'è da stupirsi, dal momento che il Math.random()metodo chiama semplicemente il nextDouble()metodo su un Randomoggetto.

float nextFloat()

Questo metodo è molto simile al nextDouble()metodo, ma il numero casuale restituito è un float. Si trova anche nella gamma 0.0- 1.0. E, come sempre in Java, l'intervallo non include il numero 1.0stesso.

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

int nextInt(int max)

Questo metodo restituisce un numero intero casuale nell'intervallo [0, max). 0è incluso nella gamma, ma maxnon lo è.

In altre parole, se vuoi ottenere un numero casuale nel set 1, 2, 3, 4, 5, 6, devi aggiungerne uno al numero casuale restituito:

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

int nextInt()

Questo metodo è simile al precedente, ma non richiede alcun parametro. Quindi qual è l'intervallo per i suoi valori di ritorno? Da -2 billiona +2 billion.

Beh, per essere precisi, da -2147483648a +2147483647.

long nextLong()

Questo metodo è simile al nextInt()metodo, ma il valore restituito cadrà da qualche parte nell'intero intervallo possibile di longs.

boolean nextBoolean()

Questo metodo restituisce un booleanvalore casuale: falseo true. Questo è molto utile quando è necessario ottenere una lunga sequenza di valori booleani casuali.

void nextBytes(byte[] data)

Questo metodo non restituisce nulla (poiché il tipo restituito è void). Invece, riempie l'array passato con valori casuali. Questo è molto utile quando hai bisogno di un grande buffer pieno di dati casuali.

double nextGaussian()

Questo metodo restituisce un numero reale casuale nell'intervallo 0.0- 1.0. Tuttavia, i numeri non sono distribuiti uniformemente in questo intervallo. Invece, seguono una distribuzione normale .

I valori vicini al centro dell'intervallo ( 0.5) si verificano più spesso dei valori alle estremità dell'intervallo.

Classe casuale

Nel nostro caso, il picco della distribuzione del valore sarà a0.5