pseudorandom number generator (tsz. pseudorandom number generators)
A pszeudovéletlenszám-generátor (PRNG, azaz pseudorandom number generator) olyan algoritmus, amely véletlenszerűnek tűnő számokat állít elő, de valójában determinisztikus módon működik egy kezdőérték (seed) alapján. C++ nyelven számos lehetőség áll rendelkezésre a véletlenszám-generálásra, beleértve a régebbi rand()
függvényt és az újabb <random>
könyvtárat.
rand()
és srand()
függvényekA C++ korábbi verzióiban az rand()
függvényt használták véletlenszám-generálásra. Ez egy 0 és RAND_MAX
közötti egész számot ad vissza. A srand()
segítségével beállítható a kezdőérték.
Példa:
#include <iostream>
#include <cstdlib>
#include <ctime>
int main() {
std::srand(std::time(0)); // Az aktuális idővel inicializáljuk a generátort
for (int i = 0; i < 5; ++i) {
std::cout << std::rand() % 100 << std::endl; // 0 és 99 között generálunk számokat
}
return 0;
}
Hátrányai: - Az rand()
nem biztosít elég jó minőségű véletlenszámokat. - A srand()
-del való inicializálás nem biztosít tökéletesen egyenletes eloszlást.
<random>
könyvtár használataA C++11 bevezetésével a <random>
könyvtár jobb minőségű, szabványosított véletlenszám-generátorokat kínál.
Főbb elemei: - std::random_device
– valódi véletlen maggenerátor (ha elérhető). - std::mt19937
– Mersenne Twister alapú PRNG. - std::uniform_int_distribution
és std::uniform_real_distribution
– egyenletes eloszlású egész és lebegőpontos számok generálására.
Példa egy jobb véletlenszám-generátorra:
#include <iostream>
#include <random>
int main() {
std::random_device rd; // Véletlenszerű seed generálása
std::mt19937 gen(rd()); // Mersenne Twister PRNG inicializálása
std::uniform_int_distribution<int> distrib(1, 100);
for (int i = 0; i < 5; ++i) {
std::cout << distrib(gen) << std::endl; // 1 és 100 között generált számok
}
return 0;
}
Előnyei a régi rand()
-hez képest: - Jobb minőségű véletlenszámokat biztosít. - Különböző eloszlások támogatása (normal_distribution
, bernoulli_distribution
, stb.). - Könnyen paraméterezhető.
Mivel a PRNG determinisztikus, azonos seed esetén ugyanazokat az értékeket kapjuk vissza.
#include <iostream>
#include <random>
int main() {
std::mt19937 gen(42); // Fixált seed (mindig ugyanazok az értékek)
std::uniform_int_distribution<int> distrib(1, 100);
for (int i = 0; i < 5; ++i) {
std::cout << distrib(gen) << std::endl;
}
return 0;
}
Ez hasznos lehet teszteléshez vagy ismételhető eredmények biztosításához.
Az egész számok mellett véletlenszerű lebegőpontos számokat is generálhatunk.
#include <iostream>
#include <random>
int main() {
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<double> distrib(0.0, 1.0);
for (int i = 0; i < 5; ++i) {
std::cout << distrib(gen) << std::endl; // 0 és 1 közötti véletlenszámok
}
return 0;
}
Ha a generált számokat bizonyos eloszlások alapján szeretnénk kapni, például normális eloszlás szerint, azt is könnyen megtehetjük.
#include <iostream>
#include <random>
int main() {
std::random_device rd;
std::mt19937 gen(rd());
std::normal_distribution<double> distrib(50.0, 10.0); // Átlag 50, szórás 10
for (int i = 0; i < 5; ++i) {
std::cout << distrib(gen) << std::endl;
}
return 0;
}
Ha több szálat használunk, akkor minden szálhoz saját PRNG példányt kell létrehozni.
#include <iostream>
#include <random>
#include <thread>
void generate_numbers(int id) {
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<int> distrib(1, 100);
std::cout << "Thread " << id << ": " << distrib(gen) << std::endl;
}
int main() {
std::thread t1(generate_numbers, 1);
std::thread t2(generate_numbers, 2);
t1.join();
t2.join();
return 0;
}
Módszer | Előnyök | Hátrányok |
---|---|---|
rand() és srand()
|
Egyszerű, gyors | Gyenge véletlenszerűség, kiszámítható |
std::random_device
|
Valódi véletlenszámokat ad (ha támogatott) | Nem mindig elérhető minden platformon |
std::mt19937 (Mersenne Twister)
|
Gyors, jó véletlenszerűség | Seed szükséges a reprodukálhatósághoz |
Különböző eloszlások (uniform , normal , stb.)
|
Rugalmasság, statisztikailag megalapozott | Lassabb lehet, mint az rand()
|
A modern C++-ban ajánlott a <random>
könyvtárat használni az rand()
helyett, mivel pontosabb és kiszámíthatóbb eredményeket nyújt.