“Computers can’t do anything truly random. Only a person can do that.”
Traditionally, random number generators work like this:
unsigned n = 1; for (int i=0; i<5; i++) { n = n * 16807 % 2147483647; cout << n << '\n'; }
16807 282475249 1622647863 947787490 1578127215
Engine | Description |
---|---|
default_random_engine | Default random engine |
minstd_rand | Minimal Standard minstd_rand generator |
minstd_rand0 | Minimal Standard minstd_rand0 generator |
mt19937 | Mersenne Twister 19937 generator |
mt19937_64 | Mersenne Twister 19937 generator (64 bit) |
ranlux24_base | Ranlux 24 base generator |
ranlux48_base | Ranlux 48 base generator |
ranlux24 | Ranlux 24 generator |
ranlux48 | Ranlux 48 generator |
knuth_b | Knuth-B generator |
random_device | True random number generator |
Define a random-number generator, and use ()
to generate a number.
This is not a function call, because gen
is an object, not a
function. It’s operator()
.
#include <random> #include <iostream> using namespace std; int main() { default_random_engine gen; for (int i=0; i<5; i++) cout << gen() << '\n'; }
16807 282475249 1622650073 984943658 1144108930
I won’t bother with the #include
s in subsequent examples.
Here’s a different, 64-bit generator. You can use .min()
and .max()
to find out the range of a given generator.
mt19937_64 gen; cout << "min=" << gen.min() << '\n' << "max=" << gen.max() << "\n\n"; for (int i=0; i<5; i++) cout << gen() << '\n';
min=0 max=18446744073709551615 14514284786278117030 4620546740167642908 13109570281517897720 17462938647148434322 355488278567739596
random_device gen; for (int i=0; i<3; i++) cout << gen() << '\n';
4168096490 3021057923 1392440570
random_device
is, ideally, truly random, and not pseudo-random.
The hosting service Cloudflare uses a unique source of randomness.
minstd_rand a; cout << a() << ' ' << a() << '\n'; minstd_rand b; cout << b() << ' ' << b() << '\n'; minstd_rand c(123); cout << c() << ' ' << c() << '\n';
48271 182605794 48271 182605794 5937333 985676192
c
? It’s clearly a function,
because c()
yielded a number. But it seems to have a constructor …
minstd_rand a, b(1), c(123), d(8675309); cout << a() << '\n' << b() << '\n' << c() << '\n' << d() << '\n';
48271 48271 5937333 6529574
random_device gen; auto seed = gen(); minstd_rand a(seed); for (int i=0; i<5; i++) cout << a() << '\n';
1779456843 1110355747 1085401611 1262628722 617654155
You can seed with random_device
, if you know that
it’s truly random.
// seconds since start of 1970 auto seed = time(nullptr); minstd_rand a(seed); for (int i=0; i<5; i++) cout << a() << '\n';
1635916409 52311355 1828131980 1360784056 1324856387
C++ provides a more accurate time—nanoseconds make more possibilities:
auto seed = chrono::high_resolution_clock::now() .time_since_epoch().count(); minstd_rand a(seed); for (int i=0; i<5; i++) cout << a() << '\n';
774521897 1403679464 1754860247 1366527022 1518177710
|
|
mt19937 gen; uniform_int_distribution<int> dist(1,6); for (int y=0; y<10; y++) { for (int x=0; x<40; x++) cout << dist(gen) << ' '; cout << '\n'; }
5 1 6 6 1 6 6 2 4 2 1 4 2 2 4 6 6 6 6 6 1 5 6 6 6 1 3 5 5 2 1 1 3 1 6 4 5 6 6 4 4 5 1 3 6 2 6 5 5 3 5 5 5 3 3 3 4 2 2 2 5 5 1 2 2 6 1 1 1 6 5 5 5 1 2 5 6 3 1 4 3 1 3 2 5 1 5 1 2 3 3 3 3 3 4 5 5 6 5 5 2 5 5 1 4 5 1 4 1 3 3 5 6 4 3 6 4 5 2 1 5 5 2 5 4 6 5 3 6 3 6 4 4 1 1 5 1 2 2 5 6 6 2 2 5 2 2 1 6 2 3 6 2 6 2 6 4 5 3 6 3 1 5 5 4 4 4 5 6 5 2 5 5 3 5 4 3 2 4 4 1 3 1 3 4 4 5 3 6 6 1 1 4 3 3 3 1 5 3 3 1 6 5 3 2 6 4 4 1 1 4 3 2 3 4 4 5 5 5 6 3 5 1 6 2 4 6 4 1 4 5 3 4 4 6 3 1 6 3 4 1 3 6 6 1 1 5 6 5 3 6 5 1 3 3 6 2 1 5 4 3 5 6 1 2 6 2 1 1 2 1 5 6 1 4 4 4 1 1 5 6 4 4 3 3 2 4 1 3 3 1 5 2 1 1 2 2 4 2 5 3 6 1 5 6 2 6 1 3 2 3 4 3 6 6 3 3 1 1 1 5 6 3 2 2 2 3 3 1 2 1 3 6 6 6 4 4 5 1 3 2 4 3 1 5 2 1 3 1 6 2 5 4 2 5 1 4 3 3 3 4 5 2 2 5 4 2 5 5 2 2 3 3 3 4 5 5 5 1 3 6 3 5 2 3 6 3 3 3 5 2 1 4 3 4 6 5 3 5 6
mt19937 gen; uniform_real_distribution<float> dist(18.0, 25.0); for (int y=0; y<10; y++) { for (int x=0; x<10; x++) cout << fixed << setprecision(3) << dist(gen) << ' '; cout << '\n'; }
23.703 18.948 24.341 23.845 18.889 24.782 24.394 19.547 22.427 20.157 18.683 21.831 19.949 19.319 21.828 24.950 24.703 24.975 24.754 24.774 19.103 23.081 24.794 24.868 24.700 18.769 21.398 23.587 23.602 20.079 18.993 18.033 20.952 18.787 24.410 22.478 23.545 24.149 24.716 21.526 22.590 23.586 18.250 20.529 23.944 19.483 24.538 22.770 22.751 20.791 23.304 23.185 23.202 21.323 20.746 20.955 22.588 19.217 19.198 20.113 22.942 23.581 18.223 20.216 19.938 24.107 18.323 19.044 18.680 24.958 23.764 23.753 22.864 18.876 20.220 23.346 24.652 21.434 18.241 22.645 21.071 18.881 20.671 19.471 23.359 18.359 23.566 18.255 19.308 20.861 21.428 21.206 21.119 21.413 22.524 23.558 22.966 24.446 23.283 23.653
mt19937 gen; uniform_real_distribution<float> dist(18.0, 25.0); auto rng = bind(dist, gen); for (int y=0; y<10; y++) { for (int x=0; x<10; x++) cout << fixed << setprecision(3) << rng() << ' '; cout << '\n'; }
23.703 18.948 24.341 23.845 18.889 24.782 24.394 19.547 22.427 20.157 18.683 21.831 19.949 19.319 21.828 24.950 24.703 24.975 24.754 24.774 19.103 23.081 24.794 24.868 24.700 18.769 21.398 23.587 23.602 20.079 18.993 18.033 20.952 18.787 24.410 22.478 23.545 24.149 24.716 21.526 22.590 23.586 18.250 20.529 23.944 19.483 24.538 22.770 22.751 20.791 23.304 23.185 23.202 21.323 20.746 20.955 22.588 19.217 19.198 20.113 22.942 23.581 18.223 20.216 19.938 24.107 18.323 19.044 18.680 24.958 23.764 23.753 22.864 18.876 20.220 23.346 24.652 21.434 18.241 22.645 21.071 18.881 20.671 19.471 23.359 18.359 23.566 18.255 19.308 20.861 21.428 21.206 21.119 21.413 22.524 23.558 22.966 24.446 23.283 23.653
auto rng = bind(uniform_real_distribution<float>(18.0, 25.0), mt19937()); for (int y=0; y<10; y++) { for (int x=0; x<10; x++) cout << fixed << setprecision(3) << rng() << ' '; cout << '\n'; }
23.703 18.948 24.341 23.845 18.889 24.782 24.394 19.547 22.427 20.157 18.683 21.831 19.949 19.319 21.828 24.950 24.703 24.975 24.754 24.774 19.103 23.081 24.794 24.868 24.700 18.769 21.398 23.587 23.602 20.079 18.993 18.033 20.952 18.787 24.410 22.478 23.545 24.149 24.716 21.526 22.590 23.586 18.250 20.529 23.944 19.483 24.538 22.770 22.751 20.791 23.304 23.185 23.202 21.323 20.746 20.955 22.588 19.217 19.198 20.113 22.942 23.581 18.223 20.216 19.938 24.107 18.323 19.044 18.680 24.958 23.764 23.753 22.864 18.876 20.220 23.346 24.652 21.434 18.241 22.645 21.071 18.881 20.671 19.471 23.359 18.359 23.566 18.255 19.308 20.861 21.428 21.206 21.119 21.413 22.524 23.558 22.966 24.446 23.283 23.653
constexpr int nrolls=10000; auto rng = bind(bernoulli_distribution(0.42), knuth_b()); int count=0; for (int i=0; i<nrolls; i++) if (rng()) count++; cout << "true: " << count*100.0/nrolls << "%\n";
true: 41.93%
mt19937 gen; normal_distribution<double> dist(21.5, 1.5); auto rng = bind(dist, gen); map<int,int> tally; for (int i=0; i<10000; i++) tally[rng()]++; for (auto p : tally) cout << p.first << ": " << string(p.second/100,'#') << '\n';
15: 16: 17: # 18: ### 19: ########### 20: ##################### 21: ######################### 22: #################### 23: ########### 24: ### 25: 26:
mt19937 gen; uniform_int_distribution<char> dist('a','z'); for (int y=0; y<8; y++) { string pw; for (int x=0; x<12; x++) pw += dist(gen); cout << "Password: " << pw << '\n'; }
Password: vdxvdzxfqico Password: heozyzzzeszz Password: ycmuuhdakcxq Password: uwynruajwfyr Password: rktttmkkreeh Password: suaihwbdczvv Password: sditymarldjf Password: tbuaekmllmqu
With binding:
mt19937 gen; uniform_int_distribution<char> dist('a','z'); auto rng = bind(dist, gen); for (int y=0; y<8; y++) { string pw; for (int x=0; x<12; x++) pw += rng(); cout << "Password: " << pw << '\n'; }
Password: vdxvdzxfqico Password: heozyzzzeszz Password: ycmuuhdakcxq Password: uwynruajwfyr Password: rktttmkkreeh Password: suaihwbdczvv Password: sditymarldjf Password: tbuaekmllmqu
With extreme binding:
auto rng = bind(uniform_int_distribution<char>('a','z'), mt19937()); for (int y=0; y<8; y++) { string pw; for (int x=0; x<12; x++) pw += rng(); cout << "Password: " << pw << '\n'; }
Password: vdxvdzxfqico Password: heozyzzzeszz Password: ycmuuhdakcxq Password: uwynruajwfyr Password: rktttmkkreeh Password: suaihwbdczvv Password: sditymarldjf Password: tbuaekmllmqu