Condividi tramite


<random>

Definisce strutture per la generazione casuale di numeri, permettendo la creazione di numeri casuali distribuiti in modo uniforme.

Requisiti

Intestazione: <random>

Spazio dei nomi: std

Nota

La <random> libreria usa l'istruzione '#include initializer_list<>'.

Riepilogo

Un generatore di numeri casuali è un oggetto che produce una sequenza di valori pseudocasuali. Un generatore che produce valori distribuiti in modo uniforme in un intervallo specificato è un generatore di numeri casuali uniformi (URNG, Uniform Random Number Generator). Un modello di classe progettato per funzionare come URNG viene definito motore se tale classe presenta determinati tratti comuni, descritti più avanti in questo articolo. Un generatore URNG può essere associato, e in genere lo è, a una distribuzione tramite il passaggio come argomento all'oggetto operator() della distribuzione, per produrre valori distribuiti nel modo definito dalla distribuzione.

Questi collegamenti permettono di passare alle sezioni principali dell'articolo:

Suggerimenti rapidi

Ecco alcuni suggerimenti da ricordare quando si usa <random>:

  • Nella maggior parte dei casi, i generatori URNG producono bit non elaborati che devono essere modellati da distribuzioni. Si tratta std::shuffle() di un'eccezione rilevante perché usa direttamente un URNG.

  • Una singola creazione di istanza di un generatore URNG o di una distribuzione non può essere chiamata contemporaneamente in modo sicuro, poiché l'esecuzione di un generatore URNG o di una distribuzione costituisce un'operazione di modifica. Per altre informazioni, vedere Thread safety nella libreria standard C++.

  • Sono disponibili typedef predefiniti di molti motori. Per la creazione di un generatore URNG se si usa un motore, è preferibile usare questa modalità.

  • L'associazione più utile per la maggior parte delle applicazioni è costituita dal motore mt19937 con uniform_int_distribution, come mostrato nell'esempio di codice più avanti in questo articolo.

Nell'intestazione <random> sono disponibili molte opzioni selezionabili e qualsiasi opzione indicata è preferibile alla funzione rand() obsoleta di Runtime C. Per informazioni sui problemi relativi a rand() e sul modo in cui <random> li gestisce, vedere questo video.

Esempi

L'esempio di codice seguente illustra come generare alcuni numeri casuali, in questo caso cinque, usando un generatore creato con un valore di inizializzazione non deterministico.

#include <random>
#include <iostream>

using namespace std;

int main()
{
    random_device rd;   // non-deterministic generator
    mt19937 gen(rd());  // to seed mersenne twister.
                        // replace the call to rd() with a
                        // constant value to get repeatable
                        // results.

    for (int i = 0; i < 5; ++i) {
        cout << gen() << " "; // print the raw output of the generator.
    }
    cout << endl;
}
2430338871 3531691818 2723770500 3252414483 3632920437

Anche se sono numeri casuali di alta qualità e diversi ogni volta che viene eseguito il programma, essi non sono necessariamente in un intervallo utile. Per controllare l'intervallo, usare una distribuzione uniforme, come illustrato nel codice seguente:

#include <random>
#include <iostream>

using namespace std;

int main()
{
    random_device rd;   // non-deterministic generator
    mt19937 gen(rd());  // to seed mersenne twister.
    uniform_int_distribution<> dist(1,6); // distribute results between 1 and 6 inclusive.

    for (int i = 0; i < 5; ++i) {
        cout << dist(gen) << " "; // pass the generator to the distribution.
    }
    cout << endl;
}
5 1 6 1 2

L'esempio di codice successivo mostra un set più realistico di casi d'uso con generatori di numeri casuali distribuiti in modo uniforme eseguendo la riproduzione casuale del contenuto di un vettore e di una matrice.

// cl.exe /EHsc /nologo /W4 /MTd
#include <algorithm>
#include <array>
#include <iostream>
#include <random>
#include <string>
#include <vector>
#include <functional> // ref()

using namespace std;

template <typename C> void print(const C& c) {
    for (const auto& e : c) {
        cout << e << " ";
    }

    cout << endl;
}

template <class URNG>
void test(URNG& urng) {

    // Uniform distribution used with a vector
    // Distribution is [-5, 5] inclusive
    uniform_int_distribution<int> dist(-5, 5);
    vector<int> v;

    for (int i = 0; i < 20; ++i) {
        v.push_back(dist(urng));
    }

    cout << "Randomized vector: ";
    print(v);

    // Shuffle an array
    // (Notice that shuffle() takes a URNG, not a distribution)
    array<string, 26> arr = { { "H", "He", "Li", "Be", "B", "C", "N", "O", "F",
        "Ne", "Na", "Mg", "Al", "Si", "P", "S", "Cl", "Ar", "K", "Ca", "Sc",
        "Ti", "V", "Cr", "Mn", "Fe" } };

    shuffle(arr.begin(), arr.end(), urng);

    cout << "Randomized array: ";
    print(arr);
    cout << "--" << endl;
}

int main()
{
    // First run: non-seedable, non-deterministic URNG random_device
    // Slower but crypto-secure and non-repeatable.
    random_device rd;
    cout << "Using random_device URNG:" << endl;
    test(rd);

    // Second run: simple integer seed, repeatable results
    cout << "Using constant-seed mersenne twister URNG:" << endl;
    mt19937 engine1(12345);
    test(engine1);

    // Third run: random_device as a seed, different each run
    // (Desirable for most purposes)
    cout << "Using non-deterministic-seed mersenne twister URNG:" << endl;
    mt19937 engine2(rd());
    test(engine2);

    // Fourth run: "warm-up" sequence as a seed, different each run
    // (Advanced uses, allows more than 32 bits of randomness)
    cout << "Using non-deterministic-seed \"warm-up\" sequence mersenne twister URNG:" << endl;
    array<unsigned int, mt19937::state_size> seed_data;
    generate_n(seed_data.begin(), seed_data.size(), ref(rd));
    seed_seq seq(begin(seed_data), end(seed_data));
    mt19937 engine3(seq);
    test(engine3);
}
Using random_device URNG:
Randomized vector: 5 -4 2 3 0 5 -2 0 4 2 -1 2 -4 -3 1 4 4 1 2 -2
Randomized array: O Li V K C Ti N Mg Ne Sc Cl B Cr Mn Ca Al F P Na Be Si Ar Fe S He H
--
Using constant-seed mersenne twister URNG:
Randomized vector: 3 -1 -5 0 0 5 3 -4 -3 -4 1 -3 0 -3 -2 -4 5 1 -1 -1
Randomized array: Al O Ne Si Na Be C N Cr Mn H V F Sc Mg Fe K Ca S Ti B P Ar Cl Li He
--
Using non-deterministic-seed mersenne twister URNG:
Randomized vector: 5 -4 0 2 1 -2 4 4 -4 0 0 4 -5 4 -5 -1 -3 0 0 3
Randomized array: Si Fe Al Ar Na P B Sc H F Mg Li C Ti He N Mn Be O Ca Cr V K Ne Cl S
--
Using non-deterministic-seed "warm-up" sequence mersenne twister URNG:
Randomized vector: -1 3 -2 4 1 3 0 -5 5 -5 0 0 5 0 -3 3 -4 2 5 0
Randomized array: Si C Sc H Na O S Cr K Li Al Ti Cl B Mn He Fe Ne Be Ar V P Ca N Mg F
--

Questo codice illustra due sequenze casuali: la creazione di una sequenza casuale per un vettore di interi e la riproduzione casuale di una matrice di dati indicizzati, con una funzione modello di esempio. La prima chiamata alla funzione di test usa il random_device sicuro a livello di crittografia, non deterministico, non sottoponibile a seeding, non ripetibile del generatore URNG. La seconda esecuzione dei test usa mersenne_twister_engine come generatore URNG, con seeding costante a 32 bit deterministico. I risultati sono quindi ripetibili. La terza esecuzione dei test esegue il seeding di mersenne_twister_engine con un risultato non deterministico a 32 bit da random_device. La quarta esecuzione dei test procede a un'ulteriore espansione, usando una sequenza di seeding compilata con risultati di random_device, che consente di ottenere in modo efficace un risultato superiore a una casualità deterministica a 32 bit, ma non ancora sicuro a livello di crittografia. Per altre informazioni, continuare a leggere.

Elenchi categorizzati

Generatori di numeri casuali uniformi

I generatori URNG sono spesso descritti tramite e proprietà seguenti:

  1. Durata periodo: numero di iterazioni necessarie per la ripetizione della sequenza di numeri generati. È preferibile specificare un periodo lungo.

  2. Prestazioni: rapidità con cui è possibile generare i numeri e quantità di memoria necessaria. È preferibile che il valore sia basso.

  3. Qualità: livello di casualità effettiva della sequenza generata. Questa proprietà è definita spesso "casualità".

Nella sezione seguente sono elencati i generatori di numeri casuali uniformi disponibili nell'intestazione di <random>.

Generatore non deterministico

random_device Classe
Genera una sequenza casuale non deterministica e sicura a livello di crittografia usando un dispositivo esterno. È usato in genere per il seeding di un motore. Offre prestazioni ridotte ma qualità molto elevata. Per altre informazioni, vedere Note.

Typedef del motore con parametri predefiniti

Per la creazione di istanze di motori e adattatori del motore. Per altre informazioni, vedere Motori e distribuzioni.

  • default_random_engine Motore predefinito.

    typedef mt19937 default_random_engine;
    
  • knuth_b Motore Knuth.

    typedef shuffle_order_engine<minstd_rand0, 256> knuth_b;
    
  • minstd_rand0 Motore del 1988 a standard minimo (Lewis, Goodman e Miller, 1969).

    typedef linear_congruential_engine<unsigned int, 16807, 0, 2147483647> minstd_rand0;
    
  • minstd_rand Motore standard minimo minstd_rand0 aggiornato (Park, Miller e Stockmeyer, 1993).

    typedef linear_congruential_engine<unsigned int, 48271, 0, 2147483647> minstd_rand;
    
  • mt19937 Motore Mersenne Twister a 32 bit (Matsumoto e Nishimura, 1998).

    typedef mersenne_twister_engine<
        unsigned int, 32, 624, 397,
        31, 0x9908b0df,
        11, 0xffffffff,
        7, 0x9d2c5680,
        15, 0xefc60000,
        18, 1812433253> mt19937;
    
  • mt19937_64 Motore Mersenne Twister a 64 bit (Matsumoto e Nishimura, 2000).

    typedef mersenne_twister_engine<
        unsigned long long, 64, 312, 156,
        31, 0xb5026f5aa96619e9ULL,
        29, 0x5555555555555555ULL,
        17, 0x71d67fffeda60000ULL,
        37, 0xfff7eee000000000ULL,
        43, 6364136223846793005ULL> mt19937_64;
    
  • ranlux24 Motore RANLUX a 24 bit (Martin Lüscher e Fred James, 1994).

    typedef discard_block_engine<ranlux24_base, 223, 23> ranlux24;
    
  • ranlux24_base Usato come base per ranlux24.

    typedef subtract_with_carry_engine<unsigned int, 24, 10, 24> ranlux24_base;
    
  • ranlux48 Motore RANLUX a 48 bit (Martin Lüscher e Fred James, 1994).

    typedef discard_block_engine<ranlux48_base, 389, 11> ranlux48;
    
  • ranlux48_base Usato come base per ranlux48.

    typedef subtract_with_carry_engine<unsigned long long, 48, 5, 12> ranlux48_base;
    

Modelli di motore

I modelli di motore sono usati come generatori URNG autonomi o come motori di base passati ad adattatori del motore. In genere sono create istanze corrispondenti con un typedef di motore predefinito e le istanze sono passate a una distribuzione. Per altre informazioni, vedere la sezione Motori e distribuzioni.

Nome Descrizione
linear_congruential_engine Classe Genera una sequenza casuale usando l'algoritmo congruenziale lineare. È estremamente semplice e offre la qualità più bassa.
mersenne_twister_engine Classe Genera una sequenza casuale usando l'algoritmo twister Mersenne. È estremamente complesso e offre la qualità più elevata, ad eccezione della classe random_device class. Prestazioni molto elevate.
subtract_with_carry_engine Classe Genera una sequenza casuale usando l'algoritmo subtract-with-carry. Rappresenta un miglioramento rispetto linear_congruential_engine, ma offre qualità e prestazioni inferiori rispetto a mersenne_twister_engine.

Modelli di adattatore motore

Gli adattatori del motore sono modelli che adattano altri motori (di base). In genere sono create istanze corrispondenti con un typedef di motore predefinito e le istanze sono passate a una distribuzione. Per altre informazioni, vedere la sezione Motori e distribuzioni.

Nome Descrizione
discard_block_engine Classe Genera una sequenza casuale, eliminando i valori restituiti dal motore di base corrispondente.
independent_bits_engine Classe Genera una sequenza casuale con un numero specificato di bit tramite la creazione di nuovi pacchetti di bit dai valori restituiti dal motore di base corrispondente.
shuffle_order_engine Classe Genera una sequenza casuale riordinando i valori restituiti dal motore di base corrispondente.

[Modelli di motore]

Distribuzioni di numeri casuali

Nelle sezioni seguenti sono elencate le distribuzioni disponibili nell'intestazione <random>. Le distribuzioni sono un meccanismo post-elaborazione che usano in genere l'output del generatore URNG come input e distribuiscono l'output in base a una funzione di densità di probabilità statistica definita. Per altre informazioni, vedere la sezione Motori e distribuzioni.

Distribuzioni uniformi

Nome Descrizione
uniform_int_distribution Classe Produce una distribuzione uniforme di valori interi in un intervallo nell'intervallo chiuso [a, b] (inclusivo).
uniform_real_distribution Classe Produce una distribuzione uniforme di valori reali (a virgola mobile) in un intervallo che si trova nell'intervallo semiaperto [a, b) (inclusivo-esclusivo).
generate_canonical Produce una distribuzione uniforme di valori reali (a virgola mobile) con precisione specificata in [0, 1) (inclusivo-esclusivo).

[Distribuzioni di numeri casuali]

Distribuzioni di Bernoulli

Nome Descrizione
bernoulli_distribution Classe Produce una distribuzione di Bernoulli dei valori bool.
binomial_distribution Classe Produce una distribuzione binomiale di valori di tipo Integer.
geometric_distribution Classe Produce una distribuzione geometrica di valori di tipo Integer.
negative_binomial_distribution Classe Produce una distribuzione binomiale negativa di valori di tipo Integer.

[Distribuzioni di numeri casuali]

Distribuzioni normali

Nome Descrizione
cauchy_distribution Classe Produce una distribuzione Cauchy di valori reali (a virgola mobile).
chi_squared_distribution Classe Produce una distribuzione del chi quadrato di valori reali (a virgola mobile).
fisher_f_distribution Classe Produce una distribuzione F (nota anche come distribuzione F di Snedecor o distribuzione Fisher-Snedecor) di valori reali (a virgola mobile).
lognormal_distribution Classe Produce una distribuzione lognormale di valori reali (a virgola mobile).
normal_distribution Classe Produce una distribuzione normale (gaussiana) di valori reali (a virgola mobile).
student_t_distribution Classe Produce una distribuzione t di valori reali (a virgola mobile).

[Distribuzioni di numeri casuali]

Distribuzioni di Poisson

Nome Descrizione
exponential_distribution Classe Produce una distribuzione esponenziale di valori reali (a virgola mobile).
extreme_value_distribution Classe Produce una distribuzione dei valori estremi di valori reali (a virgola mobile).
gamma_distribution Classe Produce una distribuzione gamma di valori reali (a virgola mobile).
poisson_distribution Classe Produce una distribuzione di Poisson di valori di tipo Integer.
weibull_distribution Classe Produce una distribuzione Weibull di valori reali (a virgola mobile).

[Distribuzioni di numeri casuali]

Distribuzioni di campionamento

Nome Descrizione
discrete_distribution Classe Produce una distribuzione discreta di valori di tipo Integer.
piecewise_constant_distribution Classe Produce una distribuzione costante a tratti di valori reali (a virgola mobile).
piecewise_linear_distribution Classe Produce una distribuzione lineare a tratti di valori reali (a virgola mobile).

[Distribuzioni di numeri casuali]

Funzioni di utilità

In questa sezione sono elencate le funzioni di utilità generali disponibili nell'intestazione <random>.

Nome Descrizione
seed_seq Classe Genera una sequenza di seeding criptata non distorta. Usata per evitare la replica di flussi di varianti casuali. Risulta utile quando i motori creano istanze di molti generatori URNG.

Operatori

In questa sezione sono elencati gli operatori disponibili nell'intestazione <random>.

Nome Descrizione
operator== Verifica se il generatore URNG sul lato sinistro dell'operatore è uguale al motore sul lato destro.
operator!= Verifica se il generatore URNG sul lato sinistro dell'operatore è diverso dal motore sul lato destro.
operator<< Scrive le informazioni sullo stato in un flusso.
operator>> Estrae le informazioni sullo stato da un flusso.

Motori e distribuzioni

Per informazioni su ognuna di queste categorie di modelli di classe definite in <random>, vedere le sezioni seguenti. Entrambe queste categorie di modelli di classe accettano un tipo come argomento e usano nomi di parametri del modello condiviso per descrivere le proprietà del tipo consentite come tipo di argomento effettivo, come indicato di seguito:

  • IntType indica un short, int, long, long long, unsigned short, unsigned int, unsigned long o unsigned long long.

  • UIntType indica unsigned short, unsigned int, unsigned long o unsigned long long.

  • RealType indica un float, double o long double.

Motori

I modelli di motore e i modelli di adattatori del motore sono modelli i cui parametri permettono di personalizzare il generatore creato.

Un motore è un modello di classe o classe le cui istanze (generatori) fungono da origine di numeri casuali distribuiti in modo uniforme tra un valore minimo e massimo. Un adattatore del motore fornisce una sequenza di valori con proprietà di casualità diverse, accettando i valori prodotti da un altro motore di numeri casuali e applicando un algoritmo a questi valori.

Ogni motore e adattatore del motore include i membri seguenti:

  • typedefnumeric-type result_type è il tipo restituito dall'oggetto del operator()generatore. numeric-type è passato come parametro di modello durante la creazione di istanze.

  • result_type operator() restituisce valori distribuiti in modo uniforme tra min() e max().

  • result_type min() restituisce il valore minimo restituito da operator() del generatore. Gli adattatori del motore usano il risultato min() del motore di base.

  • result_type max() restituisce il valore massimo restituito da operator() del generatore. Se result_type è un tipo Integer (con valore di tipo Integer), max() è il valore massimo che può essere effettivamente restituito (inclusivo). Se result_type è un tipo a virgola mobile (con valori reali), max() è il valore più piccolo superiore a tutti gli altri valori che possono essere restituiti (non inclusivo). Gli adattatori del motore usano il risultato max() del motore di base.

  • void seed(result_type s) esegue il seeding del generatore con il valore di seeding s. Per i motori, la firma è void seed(result_type s = default_seed) per il supporto di parametri predefiniti. Gli adattatori del motore definiscono un valore void seed() distinto, come illustrato nella sottosezione seguente.

  • template <class Seq> void seed(Seq& q) inizializzazione del generatore usando un oggetto seed_seqSeq.

  • Un costruttore esplicito con argomento result_type x che crea un generatore sottoposto a seeding come se l'operazione fosse eseguita chiamando seed(x).

  • Un costruttore esplicito con argomento seed_seq& seq che crea un generatore sottoposto a seeding come se l'operazione fosse eseguita chiamando seed(seq).

  • void discard(unsigned long long count) chiama operator() count in modo efficace i tempi e rimuove ogni valore.

Gli adattatori del motore supportano anche questi membri (Engine è il primo parametro di modello di un adattatore del motore e designa il tipo del motore di base):

  • Un costruttore predefinito per inizializzare il generatore come se l'operazione fosse eseguita dal costruttore predefinito del motore.

  • Un costruttore esplicito con argomento const Engine& eng. Questo permette di supportare la costruzione di copie usando il motore di base.

  • Un costruttore esplicito con argomento Engine&& eng. Questo permette di supportare la costruzione di spostamenti usando il motore di base.

  • void seed() che inizializza il generatore con il valore di seeding predefinito del motore di base.

  • Funzione della proprietà const Engine& base() che restituisce il motore di base usato per costruire il generatore.

Ciascun motore mantiene uno stato che determina la sequenza di valori che saranno generati da chiamate successive a operator(). Gli stati dei due generatori le cui istanze sono create da motori dello stesso tipo possono essere confrontati usando operator== e operator!=. Se i due stati sono uguali, i generatori produrranno la stessa sequenza di valori. Lo stato di un oggetto può essere salvato in un flusso sotto forma di sequenza di valori non firmati a 32 bit tramite operator<< del generatore. Il salvataggio non modifica lo stato. Uno stato salvato può essere letto nel generatore le cui istanze sono create da un motore dello stesso tipo tramite operator>>.

Distribuzioni

Una distribuzione casuale di numeri casuali è un modello di classe o di classe le cui istanze trasformano un flusso di numeri casuali distribuiti uniformemente ottenuti da un motore in un flusso di numeri casuali con una distribuzione specifica. Ogni distribuzione include i membri seguenti:

  • typedefnumeric-type result_type è il tipo restituito dall'oggetto della operator()distribuzione. numeric-type è passato come parametro di modello durante la creazione di istanze.

  • template <class URNG> result_type operator()(URNG& gen) restituisce valori distribuiti in base alla definizione della distribuzione, usando gen come origine dei valori casuali distribuiti in modo uniforme e dei parametri della distribuzione archiviati.

  • template <class URNG> result_type operator()(URNG& gen, param_type p) restituisce valori distribuiti in base alla definizione della distribuzione, usando gen come origine dei valori casuali distribuiti in modo uniforme e di p della struttura di parametri.

  • typedefunspecified-type param_type è il pacchetto di parametri passati facoltativamente a operator() e viene usato al posto dei parametri archiviati per generare il relativo valore restituito.

  • Un costruttore const param& inizializza i parametri archiviati dall'argomento corrispondente.

  • param_type param() const ottiene i parametri archiviati.

  • void param(const param_type&) imposta i parametri archiviati dall'argomento corrispondente.

  • result_type min() restituisce il valore minimo restituito da operator() della distribuzione.

  • result_type max() restituisce il valore massimo restituito da operator() della distribuzione. Se result_type è un tipo Integer (con valore di tipo Integer), max() è il valore massimo che può essere effettivamente restituito (inclusivo). Se result_type è un tipo a virgola mobile (con valori reali), max() è il valore più piccolo superiore a tutti gli altri valori che possono essere restituiti (non inclusivo).

  • void reset() elimina eventuali valori memorizzati nella cache, in modo che il risultato della chiamata successiva a operator() quindi, non dipenda da alcun valore ottenuto dal motore prima della chiamata.

Una struttura di parametri è un oggetto che archivia tutti i parametri necessari per una distribuzione. Contiene:

  • typedefdistribution-type distribution_type, ovvero il tipo della distribuzione.

  • Uno o più costruttori che accettano gli stessi elenchi di parametri accettati dai costruttori della distribuzione.

  • Le stesse funzioni di accesso ai parametri della distribuzione.

  • Operatori di confronto di uguaglianza e disuguaglianza.

Per altre informazioni, vedere gli argomenti secondari di riferimento seguenti. I collegamenti corrispondenti sono disponibili in precedenza in questo articolo.

Osservazioni:

In Visual Studio sono disponibili due generatori URNG molto utili, ovvero mt19937 e random_device, come mostrato in questa tabella di confronto:

URNG Veloce Sicuro a livello di crittografia Compatibile con seeding Deterministico
mt19937 No *
random_device No No No

* Se è fornito un seeding noto.

Anche se lo standard C++ ISO non richiede che random_device sia sicuro a livello di crittografia, Visual Studio è implementato in modo da offrire questo tipo di sicurezza. Il termine "crittograficamente sicuro" non implica garanzie, ma fa riferimento a un livello minimo di entropia, e quindi al livello di prevedibilità, fornito da un algoritmo di randomizzazione specificato. Per altre informazioni, vedere l'articolo di Wikipedia Cryptographically secure pseudorandom number generator.) Poiché lo standard ISO C++ non richiede questo, altre piattaforme possono implementare random_device come semplice generatore di numeri pseudo-casuali (non crittograficamente sicuri) e può essere adatto solo come origine di inizializzazione per un altro generatore. Quando si usa random_device in codice destinato a più piattaforme, verificare la documentazione relativa alle piattaforme specifiche.

Per definizione, i risultati di random_device non sono riproducibili e, come effetto collaterale, è possibile che l'esecuzione risulti significativamente più lenta rispetto ad altri generatori URNG. La maggior parte delle applicazioni che non devono essere crittograficamente sicure usano mt19937 o un motore simile, anche se è consigliabile eseguirne il seeding tramite una chiamata a random_device, come illustrato nell'esempio di codice.

Vedi anche

Riferimento file di intestazione