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: random_demo.cpp,v 1.17 2005/05/10 20:40:59 jmaurer Exp $ |
---|
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 | |
---|
22 | // Sun CC doesn't handle boost::iterator_adaptor yet |
---|
23 | #if !defined(__SUNPRO_CC) || (__SUNPRO_CC > 0x530) |
---|
24 | #include <boost/generator_iterator.hpp> |
---|
25 | #endif |
---|
26 | |
---|
27 | #ifdef BOOST_NO_STDC_NAMESPACE |
---|
28 | namespace std { |
---|
29 | using ::time; |
---|
30 | } |
---|
31 | #endif |
---|
32 | |
---|
33 | // This is a typedef for a random number generator. |
---|
34 | // Try boost::mt19937 or boost::ecuyer1988 instead of boost::minstd_rand |
---|
35 | typedef boost::minstd_rand base_generator_type; |
---|
36 | |
---|
37 | // This is a reproducible simulation experiment. See main(). |
---|
38 | void experiment(base_generator_type & generator) |
---|
39 | { |
---|
40 | // Define a uniform random number distribution of integer values between |
---|
41 | // 1 and 6 inclusive. |
---|
42 | typedef boost::uniform_int<> distribution_type; |
---|
43 | typedef boost::variate_generator<base_generator_type&, distribution_type> gen_type; |
---|
44 | gen_type die_gen(generator, distribution_type(1, 6)); |
---|
45 | |
---|
46 | #if !defined(__SUNPRO_CC) || (__SUNPRO_CC > 0x530) |
---|
47 | // If you want to use an STL iterator interface, use iterator_adaptors.hpp. |
---|
48 | // Unfortunately, this doesn't work on SunCC yet. |
---|
49 | boost::generator_iterator<gen_type> die(&die_gen); |
---|
50 | for(int i = 0; i < 10; i++) |
---|
51 | std::cout << *die++ << " "; |
---|
52 | std::cout << '\n'; |
---|
53 | #endif |
---|
54 | } |
---|
55 | |
---|
56 | int main() |
---|
57 | { |
---|
58 | // Define a random number generator and initialize it with a reproducible |
---|
59 | // seed. |
---|
60 | // (The seed is unsigned, otherwise the wrong overload may be selected |
---|
61 | // when using mt19937 as the base_generator_type.) |
---|
62 | base_generator_type generator(42u); |
---|
63 | |
---|
64 | std::cout << "10 samples of a uniform distribution in [0..1):\n"; |
---|
65 | |
---|
66 | // Define a uniform random number distribution which produces "double" |
---|
67 | // values between 0 and 1 (0 inclusive, 1 exclusive). |
---|
68 | boost::uniform_real<> uni_dist(0,1); |
---|
69 | boost::variate_generator<base_generator_type&, boost::uniform_real<> > uni(generator, uni_dist); |
---|
70 | |
---|
71 | std::cout.setf(std::ios::fixed); |
---|
72 | // You can now retrieve random numbers from that distribution by means |
---|
73 | // of a STL Generator interface, i.e. calling the generator as a zero- |
---|
74 | // argument function. |
---|
75 | for(int i = 0; i < 10; i++) |
---|
76 | std::cout << uni() << '\n'; |
---|
77 | |
---|
78 | /* |
---|
79 | * Change seed to something else. |
---|
80 | * |
---|
81 | * Caveat: std::time(0) is not a very good truly-random seed. When |
---|
82 | * called in rapid succession, it could return the same values, and |
---|
83 | * thus the same random number sequences could ensue. If not the same |
---|
84 | * values are returned, the values differ only slightly in the |
---|
85 | * lowest bits. A linear congruential generator with a small factor |
---|
86 | * wrapped in a uniform_smallint (see experiment) will produce the same |
---|
87 | * values for the first few iterations. This is because uniform_smallint |
---|
88 | * takes only the highest bits of the generator, and the generator itself |
---|
89 | * needs a few iterations to spread the initial entropy from the lowest bits |
---|
90 | * to the whole state. |
---|
91 | */ |
---|
92 | generator.seed(static_cast<unsigned int>(std::time(0))); |
---|
93 | |
---|
94 | std::cout << "\nexperiment: roll a die 10 times:\n"; |
---|
95 | |
---|
96 | // You can save a generator's state by copy construction. |
---|
97 | base_generator_type saved_generator = generator; |
---|
98 | |
---|
99 | // When calling other functions which take a generator or distribution |
---|
100 | // as a parameter, make sure to always call by reference (or pointer). |
---|
101 | // Calling by value invokes the copy constructor, which means that the |
---|
102 | // sequence of random numbers at the caller is disconnected from the |
---|
103 | // sequence at the callee. |
---|
104 | experiment(generator); |
---|
105 | |
---|
106 | std::cout << "redo the experiment to verify it:\n"; |
---|
107 | experiment(saved_generator); |
---|
108 | |
---|
109 | // After that, both generators are equivalent |
---|
110 | assert(generator == saved_generator); |
---|
111 | |
---|
112 | // as a degenerate case, you can set min = max for uniform_int |
---|
113 | boost::uniform_int<> degen_dist(4,4); |
---|
114 | boost::variate_generator<base_generator_type&, boost::uniform_int<> > deg(generator, degen_dist); |
---|
115 | std::cout << deg() << " " << deg() << " " << deg() << std::endl; |
---|
116 | |
---|
117 | #ifndef BOOST_NO_OPERATORS_IN_NAMESPACE |
---|
118 | { |
---|
119 | // You can save the generator state for future use. You can read the |
---|
120 | // state back in at any later time using operator>>. |
---|
121 | std::ofstream file("rng.saved", std::ofstream::trunc); |
---|
122 | file << generator; |
---|
123 | } |
---|
124 | #endif |
---|
125 | // Some compilers don't pay attention to std:3.6.1/5 and issue a |
---|
126 | // warning here if "return 0;" is omitted. |
---|
127 | return 0; |
---|
128 | } |
---|