HOWTO · C++
Genera un numero casuale tra 0 e 1 in C++
In questo articolo viene illustrato come creare un numero casuale compreso tra 0 e 1 intervallo C++
In questa pagina
Per generare un valore pseudo-casuale in virgola mobile da 0 fino a 1, escluso, abbina un motore casuale di C++11 a std::uniform_real_distribution<double>. L’esempio usa un seed fisso, quindi lo stesso motore e lo stesso seed riproducono una sequenza su una determinata implementazione. Per il nuovo codice C++, usa <random>; riserva std::rand alla manutenzione del codice meno recente.
Generare un numero in virgola mobile con <random> di C++11
Includi <random>, crea un motore e passalo a una distribuzione ogni volta che ti serve un valore. Il motore genera una sequenza di bit pseudo-casuali; la distribuzione mappa quei bit su valori del tipo e dell’intervallo richiesti. Questo esempio completo stampa cinque valori. Il seed fisso rende le esecuzioni ripetibili con la stessa implementazione della libreria standard.
#include <iostream>
#include <random>
int main() {
std::mt19937 engine(2026);
std::uniform_real_distribution<double> distribution(0.0, 1.0);
for (int i = 0; i < 5; ++i) {
std::cout << distribution(engine) << '\n';
}
}
Le cifre stampate dipendono dall’implementazione della libreria standard. Con una determinata implementazione, usare lo stesso motore e lo stesso seed avvia la medesima sequenza. Per ottenere un’altra sequenza, usa un seed diverso oppure inizializza il motore una sola volta con std::random_device; non è detto che questo dispositivo fornisca entropia non deterministica su tutti i sistemi.
Capire l’intervallo dei risultati e scegliere un motore
Per std::uniform_real_distribution<double>(0.0, 1.0), l’intervallo specificato è semiaperto: può essere restituito 0, mentre 1 è escluso. L’argomento del template seleziona il tipo in virgola mobile del risultato (float, double o long double). Una distribuzione richiede un motore come argomento: non è un generatore autonomo.
Il motore determina la sequenza pseudo-casuale e il seed stabilisce da dove inizia quella sequenza. std::mt19937 è un motore standard molto usato, con un algoritmo specificato. std::default_random_engine è comodo quando il motore specifico non è importante, ma la sua scelta dipende dall’implementazione; è quindi meno adatto se vuoi la stessa sequenza con librerie standard diverse. Inizializza il motore una volta e riutilizzalo: reimpostare il seed prima di ogni estrazione può ripetere i valori e compromettere la sequenza. Queste funzionalità sono adatte a simulazioni, giochi e alla normale generazione di valori casuali, ma non a segreti crittografici.
Usare std::rand solo per il codice legacy
Il codice meno recente può usare std::rand, dichiarata in <cstdlib>. Restituisce un intero da 0 a RAND_MAX, estremi inclusi. Converti il valore in virgola mobile prima di dividerlo, per evitare la divisione intera. Per esempio, l’espressione static_cast<double>(std::rand()) / (static_cast<double>(RAND_MAX) + 1.0) ridimensiona l’intero nell’intervallo desiderato.
Questo ridimensionamento mantiene il risultato minore di 1, anche quando std::rand restituisce RAND_MAX. Per variare i risultati tra le esecuzioni, chiama std::srand una sola volta prima di generarli, spesso usando un seed basato sull’ora; esecuzioni successive possono comunque usare lo stesso seed e inizializzare il generatore non ne migliora la qualità. RAND_MAX dipende dall’implementazione e std::rand offre meno controllo sul motore e sulla sequenza rispetto a <random>. Per il nuovo codice, preferisci un motore e una distribuzione di C++11; ricorri alla funzione legacy solo quando è richiesta da un’interfaccia esistente.