“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';
1601681259 1142212507 1247349228
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';
1023815595 561417834 1104123521 897330945 316886105
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';
1312629845 450243260 1157895820 232246751 918280181
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';
1245727394 817436127 594756439 1926673873 1400222954
|
|
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