Public Group

Seeding the new C++0x RNG

This topic is 2786 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

So I've activated support for the new features of C++0x for my compiler, and the following code compiles and runs:

#include <random>#include <functional>#include <iostream>#include <iomanip>int main(){    std::uniform_int_distribution<int> distribution(1, 6);    std::mt19937 rng;    auto generator = std::bind(distribution, rng);    // roll a set of six 3d6 stats, several times    for(int set=1; set<=10; set++){        for (int stat=1; stat<=6; stat++){            int rnd_3d6 =0;            for(int die=1; die<=3; die++){                rnd_3d6 += generator();            }            std::cout << std::setw(3) << rnd_3d6;        }        std::cout << std::endl;    }}

Output:
12 13 12  7  8 1813 17 10 12  5 1117 13 10 13 13 1310  6 11 10  3 16 8 14  8  6 11  6 9 12 16 12 10 10 7 15 13  8 12 1514 13  6  8 13 10 9  9 11 14 12 1014 13 13 13 12 10

But without a seeding function it produces the same set of numbers on every run. How do I seed this new beast? Also, I know that std::uniform_int_distribution isn't what I really want. Ideally I think it's a binomial_distribution over the range [3,18].

[Edited by - AngleWyrm on December 2, 2010 1:05:37 AM]

Share on other sites
my19937 is a typedef, at least in Visual C++, for mersenne_twister class. Here is the documentation for that class. All that remains is you find a way to supply a new seed every time you create a new random number generator. I suggest something like the time function.

Share on other sites
Thanks; with that info, I've put the seeding function into the constructor and it works.

#include <random>#include <functional>#include <iostream>#include <iomanip>int main(){    std::uniform_int_distribution<int> distribution(1, 6);    std::mt19937 rng(time(NULL)); // seed rng during construction    auto generator = std::bind(distribution, rng);    // roll a set of six 3d6 stats, several times    for(int set=1; set<=10; set++){        for (int stat=1; stat<=6; stat++){            int rnd_3d6 =0;            for(int die=1; die<=3; die++){                rnd_3d6 += generator();            }            std::cout << std::setw(3) << rnd_3d6;        }        std::cout << std::endl;    }}

Now all I gotta do is figure out the binomial_distribution thing. When I substitute binomial_distribution in place of uniform_int_distribution, it keeps generating 1*3=3's across the board, so either I'm not using it correctly or it doesn't work the way I think it does.

Share on other sites
A binomial distribution gives you results that model a set of possibly-weighted coin flips - it's binomial because there are two outcomes for each thing that gets added together. You can't use this (at least, not with any real accuracy) to model six-sided dice. Just keep doing what you're doing with the loop.

Share on other sites
Quote:
 Original post by nobodynewsmy19937 is a typedef, at least in Visual C++

It is also per The Next Holy Standard:

Quote:
N3126=10-01 16

[...]
typedef see below mt19937;typedef see below mt19937_64;
[...]

The standard even (partially) defines the output:

Quote:

26.5.5 Engines and adaptors with predefined parameters

[...]
typedef mersenne_twister_engine<uint_fast32_t, 32,   624, 397, 31, 0x9908b0df, 11, 0xffffffff, 7, 0x9d2c5680, 15,   0xefc60000, 18, 1812433253>mt19937;

Required behavior: The 10000th consecutive invocation of a default-constructed object of type mt19937 shall produce the value 4123659995.[...]

The latter thing being very important to me, as this is the first time I can portably rely on the standard library for generating content procedurally.

Share on other sites
Quote:
 Original post by ZahlmanA binomial distribution gives you results that model a set of possibly-weighted coin flips - it's binomial because there are two outcomes for each thing that gets added together. You can't use this (at least, not with any real accuracy) to model six-sided dice. Just keep doing what you're doing with the loop.

Right you are, and I'll be keeping the for loop because it has a definite min and max of the dice. The distribution that 3d6 begins to represent is the Normal distribution, which can be specified with a mean and a standard deviation. I tried using a mean of 10.5 and a standard deviation of 2.5, and it seemed close to producing values from the distribution of 3d6.

#include <random>#include <functional>#include <iostream>#include <iomanip>int main(){    std::normal_distribution<double> distribution(10.5, 2.5);    std::mt19937 rng(time(NULL));    // roll a set of six 3d6 stats, several times    for(int set=1; set<=10; set++){        for (int stat=1; stat<=6; stat++){             std::cout << std::setw(3) << (int) distribution(rng);        }        std::cout << std::endl;    }}

The only difference of course is that a normal distribution is unbounded, and merely has decreasing likelihood as the numbers spread away from average. It means it is possible (but highly unlikely) to roll a -1 or a 20. It isn't dice, but it's interesting.

[Edited by - AngleWyrm on December 2, 2010 5:50:33 AM]

1. 1
Rutin
24
2. 2
JoeJ
20
3. 3
4. 4
5. 5

• 9
• 46
• 41
• 23
• 13
• Forum Statistics

• Total Topics
631749
• Total Posts
3002046
×