C++
Generazione di numeri casuali
Ricerca…
Osservazioni
La generazione di numeri casuali in C ++ è fornita dall'intestazione <random>
. Questa intestazione definisce dispositivi casuali, generatori pseudo-casuali e distribuzioni.
I dispositivi casuali restituiscono numeri casuali forniti dal sistema operativo. Dovrebbero essere utilizzati per l'inizializzazione di generatori pseudo casuali o direttamente per scopi crittografici.
I generatori pseudo-casuali restituiscono numeri pseudo-casuali interi in base al seme iniziale. L'intervallo di numeri pseudo-casuali si estende in genere su tutti i valori di un tipo senza segno. Tutti i generatori pseudo-casuali nella libreria standard restituiranno gli stessi numeri per lo stesso seme iniziale per tutte le piattaforme.
Le distribuzioni consumano numeri casuali da generatori pseudo casuali o dispositivi casuali e producono numeri casuali con distribuzione necessaria. Le distribuzioni non sono indipendenti dalla piattaforma e possono produrre numeri diversi per gli stessi generatori con le stesse sementi iniziali su piattaforme diverse.
Vero generatore di valori casuali
Per generare valori casuali veri che possono essere usati per la crittografia, std::random_device
deve essere usato come generatore.
#include <iostream>
#include <random>
int main()
{
std::random_device crypto_random_generator;
std::uniform_int_distribution<int> int_distribution(0,9);
int actual_distribution[10] = {0,0,0,0,0,0,0,0,0,0};
for(int i = 0; i < 10000; i++) {
int result = int_distribution(crypto_random_generator);
actual_distribution[result]++;
}
for(int i = 0; i < 10; i++) {
std::cout << actual_distribution[i] << " ";
}
return 0;
}
std::random_device
è usato allo stesso modo di un generatore di valori pseudo casuali.
Tuttavia, std::random_device
può essere implementato in termini di un motore di numeri pseudo-casuali definito dall'implementazione se una sorgente non deterministica (ad esempio un dispositivo hardware) non è disponibile all'implementazione.
La rilevazione di tali implementazioni dovrebbe essere possibile tramite la funzione membro entropy
(che restituisce zero quando il generatore è completamente deterministico), ma molte librerie popolari (sia libstdc ++ di GCC che libc ++ di LLVM) restituiscono sempre zero, anche quando usano casualità esterna di alta qualità .
Generazione di un numero pseudo-casuale
Un generatore di numeri pseudo casuali genera valori che possono essere indovinati sulla base di valori generati in precedenza. In altre parole: è deterministico. Non utilizzare un generatore di numeri pseudo casuali in situazioni in cui è richiesto un numero casuale reale.
#include <iostream>
#include <random>
int main()
{
std::default_random_engine pseudo_random_generator;
std::uniform_int_distribution<int> int_distribution(0, 9);
int actual_distribution[10] = {0,0,0,0,0,0,0,0,0,0};
for(int i = 0; i < 10000; i++) {
int result = int_distribution(pseudo_random_generator);
actual_distribution[result]++;
}
for(int i = 0; i <= 9; i++) {
std::cout << actual_distribution[i] << " ";
}
return 0;
}
Questo codice crea un generatore di numeri casuali e una distribuzione che genera numeri interi nell'intervallo [0,9] con uguale probabilità. Quindi conta quante volte ogni risultato è stato generato.
Il parametro template di std::uniform_int_distribution<T>
specifica il tipo di intero che dovrebbe essere generato. Usa std::uniform_real_distribution<T>
per generare float o double.
Utilizzo del generatore per più distribuzioni
Il generatore di numeri casuali può (e dovrebbe) essere utilizzato per più distribuzioni.
#include <iostream>
#include <random>
int main()
{
std::default_random_engine pseudo_random_generator;
std::uniform_int_distribution<int> int_distribution(0, 9);
std::uniform_real_distribution<float> float_distribution(0.0, 1.0);
std::discrete_distribution<int> rigged_dice({1,1,1,1,1,100});
std::cout << int_distribution(pseudo_random_generator) << std::endl;
std::cout << float_distribution(pseudo_random_generator) << std::endl;
std::cout << (rigged_dice(pseudo_random_generator) + 1) << std::endl;
return 0;
}
In questo esempio, viene definito un solo generatore. Successivamente viene utilizzato per generare un valore casuale in tre diverse distribuzioni. La distribuzione rigged_dice
genererà un valore compreso tra 0 e 5, ma quasi sempre genera un 5
, perché la possibilità di generare un 5
è 100 / 105
.