1 | /* boost random_demo.cpp profane demo |
2 | * |
3 | * Copyright Jens Maurer 2000 |
4 | * Distributed under the Boost Software License, Version 1.0. (See |
5 | * accompanying file LICENSE_1_0.txt or copy at |
6 | * http://www.boost.org/LICENSE_1_0.txt) |
7 | * |
8 | * $Id$ |
9 | * |
10 | * A short demo program how to use the random number library. |
11 | */ |
12 | |
13 | #include <iostream> |
14 | #include <fstream> |
15 | #include <ctime> // std::time |
16 | |
17 | #include <boost/random/linear_congruential.hpp> |
18 | #include <boost/random/uniform_int.hpp> |
19 | #include <boost/random/uniform_real.hpp> |
20 | #include <boost/random/variate_generator.hpp> |
21 | #include <boost/generator_iterator.hpp> |
22 | |
23 | // This is a typedef for a random number generator. |
24 | // Try boost::mt19937 or boost::ecuyer1988 instead of boost::minstd_rand |
25 | typedef boost::minstd_rand base_generator_type; |
26 | |
27 | // This is a reproducible simulation experiment. See main(). |
28 | void experiment(base_generator_type & generator) |
29 | { |
30 | // Define a uniform random number distribution of integer values between |
31 | // 1 and 6 inclusive. |
32 | typedef boost::uniform_int<> distribution_type; |
33 | typedef boost::variate_generator<base_generator_type&, distribution_type> gen_type; |
34 | gen_type die_gen(generator, distribution_type(1, 6)); |
35 | |
36 | // If you want to use an STL iterator interface, use iterator_adaptors.hpp. |
37 | boost::generator_iterator<gen_type> die(&die_gen); |
38 | for(int i = 0; i < 10; i++) |
39 | std::cout << *die++ << " " ; |
40 | std::cout << '\n'; |
41 | } |
42 | |
43 | int main() |
44 | { |
45 | // Define a random number generator and initialize it with a reproducible |
46 | // seed. |
47 | base_generator_type generator(42); |
48 | |
49 | std::cout << "10 samples of a uniform distribution in [0..1):\n" ; |
50 | |
51 | // Define a uniform random number distribution which produces "double" |
52 | // values between 0 and 1 (0 inclusive, 1 exclusive). |
53 | boost::uniform_real<> uni_dist(0,1); |
54 | boost::variate_generator<base_generator_type&, boost::uniform_real<> > uni(generator, uni_dist); |
55 | |
56 | std::cout.setf(std::ios::fixed); |
57 | // You can now retrieve random numbers from that distribution by means |
58 | // of a STL Generator interface, i.e. calling the generator as a zero- |
59 | // argument function. |
60 | for(int i = 0; i < 10; i++) |
61 | std::cout << uni() << '\n'; |
62 | |
63 | /* |
64 | * Change seed to something else. |
65 | * |
66 | * Caveat: std::time(0) is not a very good truly-random seed. When |
67 | * called in rapid succession, it could return the same values, and |
68 | * thus the same random number sequences could ensue. If not the same |
69 | * values are returned, the values differ only slightly in the |
70 | * lowest bits. A linear congruential generator with a small factor |
71 | * wrapped in a uniform_smallint (see experiment) will produce the same |
72 | * values for the first few iterations. This is because uniform_smallint |
73 | * takes only the highest bits of the generator, and the generator itself |
74 | * needs a few iterations to spread the initial entropy from the lowest bits |
75 | * to the whole state. |
76 | */ |
77 | generator.seed(x0: static_cast<unsigned int>(std::time(timer: 0))); |
78 | |
79 | std::cout << "\nexperiment: roll a die 10 times:\n" ; |
80 | |
81 | // You can save a generator's state by copy construction. |
82 | base_generator_type saved_generator = generator; |
83 | |
84 | // When calling other functions which take a generator or distribution |
85 | // as a parameter, make sure to always call by reference (or pointer). |
86 | // Calling by value invokes the copy constructor, which means that the |
87 | // sequence of random numbers at the caller is disconnected from the |
88 | // sequence at the callee. |
89 | experiment(generator); |
90 | |
91 | std::cout << "redo the experiment to verify it:\n" ; |
92 | experiment(generator&: saved_generator); |
93 | |
94 | // After that, both generators are equivalent |
95 | assert(generator == saved_generator); |
96 | |
97 | // as a degenerate case, you can set min = max for uniform_int |
98 | boost::uniform_int<> degen_dist(4,4); |
99 | boost::variate_generator<base_generator_type&, boost::uniform_int<> > deg(generator, degen_dist); |
100 | std::cout << deg() << " " << deg() << " " << deg() << std::endl; |
101 | |
102 | { |
103 | // You can save the generator state for future use. You can read the |
104 | // state back in at any later time using operator>>. |
105 | std::ofstream file("rng.saved" , std::ofstream::trunc); |
106 | file << generator; |
107 | } |
108 | |
109 | return 0; |
110 | } |
111 | |