C++
Generowanie liczb losowych
Szukaj…
Uwagi
Generowanie liczb losowych w C ++ zapewnia nagłówek <random>
. Ten nagłówek definiuje losowe urządzenia, pseudolosowe generatory i rozkłady.
Losowe urządzenia zwracają losowe liczby dostarczane przez system operacyjny. Powinny być używane do inicjalizacji generatorów pseudolosowych lub bezpośrednio do celów kryptograficznych.
Generatory pseudolosowe zwracają pseudolosowe liczby całkowite w oparciu o ich początkowe ziarno. Pseudolosowy zakres liczb zwykle obejmuje wszystkie wartości typu bez znaku. Wszystkie generatory pseudolosowe w standardowej bibliotece zwracają te same liczby dla tego samego początkowego ziarna dla wszystkich platform.
Dystrybucje zużywają liczby losowe z generatorów pseudolosowych lub urządzeń losowych i wytwarzają liczby losowe z niezbędnym rozkładem. Dystrybucje nie są niezależne od platformy i mogą wytwarzać różne liczby dla tych samych generatorów z tymi samymi początkowymi nasionami na różnych platformach.
Prawdziwy generator wartości losowych
Aby wygenerować prawdziwe losowe wartości, które można wykorzystać w kryptografii, jako generator należy użyć std::random_device
.
#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
jest używane w taki sam sposób, jak używany jest pseudolosowy generator wartości.
Jednak urządzenie std::random_device
można zaimplementować w kategoriach zdefiniowanego implementacji silnika liczb pseudolosowych, jeśli źródło niedeterministyczne (np. Urządzenie sprzętowe) nie jest dostępne dla implementacji.
Wykrywanie takich implementacji powinno być możliwe za pomocą funkcji elementu entropy
(która zwraca zero, gdy generator jest całkowicie deterministyczny), ale wiele popularnych bibliotek (zarówno libstdc ++ GCC, jak i libc ++ LLVM) zawsze zwraca zero, nawet jeśli używa wysokiej jakości losowości zewnętrznej .
Generowanie liczby pseudolosowej
Generator liczb pseudolosowych generuje wartości, które można odgadnąć na podstawie wcześniej wygenerowanych wartości. Innymi słowy: jest deterministyczny. Nie używaj generatora liczb pseudolosowych w sytuacjach, w których wymagana jest prawdziwa liczba losowa.
#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;
}
Ten kod tworzy generator liczb losowych i rozkład, który generuje liczby całkowite z zakresu [0,9] z jednakowym prawdopodobieństwem. Następnie zlicza, ile razy każdy wynik został wygenerowany.
Parametr szablonu std::uniform_int_distribution<T>
określa typ liczby całkowitej, którą należy wygenerować. Użyj std::uniform_real_distribution<T>
do generowania std::uniform_real_distribution<T>
lub podwójnych.
Korzystanie z generatora do wielu dystrybucji
Generator liczb losowych może (i powinien) być używany do wielu dystrybucji.
#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;
}
W tym przykładzie zdefiniowano tylko jeden generator. Jest następnie wykorzystywany do generowania wartości losowej w trzech różnych rozkładach. Rozkład rigged_dice
wygeneruje wartość między 0 a 5, ale prawie zawsze generuje 5
, ponieważ szansa na wygenerowanie 5
wynosi 100 / 105
.