La classe Random per la Generazione di Numeri Casuali in Java
- La classe
Random
in Java è utilizzata per generare numeri casuali e sequenze di valori pseudocasuali. - I numeri generati sono distribuiti uniformemente e possono essere di diversi tipi, come
int
,long
,float
,double
, eboolean
. - La classe include metodi per generare numeri casuali in vari formati e per riempire array.
- A partire da JDK 8, la classe
Random
supporta gli Stream, permettendo di generare sequenze di valori casuali in modo più fluido e funzionale.
La classe Random
La classe Random
è un generatore di numeri pseudocasuali. Questi sono chiamati numeri pseudocasuali perché sono semplicemente sequenze distribuite uniformemente. A partire da JDK 17, Random
implementa la nuova interfaccia RandomGenerator
, che fornisce un'interfaccia standardizzata per i generatori di valori casuali.
Random
definisce i seguenti costruttori:
Random()
Random(long *seme*)
La prima versione crea un generatore di numeri che utilizza un seme ragionevolmente unico. La seconda forma consente di specificare manualmente un valore di seme.
Se si inizializza un oggetto Random
con un seme, si definisce il punto di partenza per la sequenza casuale. Se si usa lo stesso seme per inizializzare un altro oggetto Random
, verrà estratta la stessa sequenza casuale. Se si vogliono generare sequenze diverse, bisogna specificare valori di seme diversi. Un modo per farlo è utilizzare l'ora corrente per dare il seme ad un oggetto Random
. Questo approccio riduce la possibilità di ottenere sequenze ripetute.
I metodi pubblici principali forniti da Random
sono mostrati nella tabella che segue:
Metodo | Descrizione |
---|---|
boolean nextBoolean() |
Restituisce il prossimo numero casuale boolean , ossia genera un booleano casuale. |
void nextBytes(byte[] valori) |
Riempie l'array valori con valori generati casualmente. |
double nextDouble() |
Restituisce il prossimo numero casuale double . |
float nextFloat() |
Restituisce il prossimo numero casuale float . |
double nextGaussian() |
Restituisce il prossimo numero casuale Gaussiano. |
int nextInt() |
Restituisce il prossimo numero casuale int . |
int nextInt(int n) |
Restituisce il prossimo numero casuale int nell'intervallo da zero a n . |
long nextLong() |
Restituisce il prossimo numero casuale long . |
void setSeed(long nuovoSeme) |
Imposta il valore del seme (cioè, il punto di partenza per il generatore di numeri casuali) a quello specificato da nuovoSeme . |
Come si può vedere, ci sono sette tipi di numeri casuali che si possono estrarre da un oggetto Random
. I valori boolean
casuali sono disponibili attraverso nextBoolean()
. I byte casuali possono essere ottenuti chiamando nextBytes()
. Gli interi possono essere estratti tramite il metodo nextInt()
. Gli interi long possono essere ottenuti con nextLong()
. I metodi nextFloat()
e nextDouble()
restituiscono rispettivamente valori float
e double
tra 0.0 e 1.0. Infine, nextGaussian()
restituisce un valore double
centrato su 0.0 con una deviazione standard di 1.0. Questa è quella che è conosciuta come una curva a campana o gaussiana.
Ecco un esempio che dimostra la sequenza prodotta da nextGaussian()
. Ottiene 100 valori Gaussiani casuali e calcola la media di questi valori. Il programma conta anche il numero di valori che cadono entro due deviazioni standard, più o meno, utilizzando incrementi di 0.5 per ogni categoria. Il risultato viene visualizzato graficamente di lato sullo schermo.
// Esempio di valori Gaussiani casuali.
import java.util.Random;
class DemoGaussian {
public static void main(String[] args) {
// Crea un oggetto Random.
Random r = new Random();
// Variabile che contiene il valore casuale
double val;
// Accumulatore per la somma dei valori
double somma = 0;
// Array per la distribuzione dei valori
int[] campana = new int[10];
// Genera 100 valori casuali distribuiti
// secondo la distribuzione normale (gaussiana).
// Conta quanti valori cadono in ciascuna categoria.
// La distribuzione è divisa in 10 categorie,
// da -2.5 a +2.5, con incrementi di 0.5.
for (int i = 0; i < 100; i++) {
val = r.nextGaussian();
somma += val;
double t = -2;
for (int x = 0; x < 10; x++, t += 0.5)
if (val < t) {
campana[x]++;
break;
}
}
// Visualizza la media
System.out.println("Media dei valori: " +
(somma / 100));
// Visualizza la distribuzione dei valori
// Sotto forma di istogramma.
System.out.println("Distribuzione dei valori:");
for (int i = 0; i < 10; i++) {
// Stampa gli asterischi per rappresentare la frequenza
// dei valori in ciascuna categoria.
for (int x = campana[i]; x > 0; x--) {
System.out.print("*");
}
System.out.println();
}
}
}
Ecco un esempio di esecuzione del programma. Come si può vedere, si ottiene una distribuzione simile a una campana dei numeri.
Media dei valori: 0.07509980085218296
Distribuzione dei valori:
****
*****
*******************
*********************
***************
*********************
**********
*****
È utile evidenziare che JDK 8 ha aggiunto tre metodi a Random
che supportano gli Stream (che vedremo nelle prossime lezioni). Sono chiamati doubles()
, ints()
e longs()
, e ognuno restituisce un riferimento a uno stream che contiene una sequenza di valori pseudocasuali del tipo specificato. Ogni metodo definisce diversi overload. Ecco le loro forme più semplici:
DoubleStream doubles()
IntStream ints()
LongStream longs()
Il metodo doubles()
restituisce uno stream che contiene valori double
pseudocasuali. (L'intervallo di questi valori sarà minore di 1.0 ma maggiore o uguale a 0.0.) Il metodo ints()
restituisce uno stream che contiene valori int
pseudocasuali. Il metodo longs()
restituisce uno stream che contiene valori long
pseudocasuali. Per questi tre metodi, lo stream restituito è effettivamente infinito. Sono forniti diversi overload di ogni metodo che ti permettono di specificare la dimensione dello stream, un'origine e un limite superiore.