Sign in to follow this  

Seeding the new C++0x RNG

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

If you intended to correct an error in the post then please contact us.

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 18
13 17 10 12 5 11
17 13 10 13 13 13
10 6 11 10 3 16
8 14 8 6 11 6
9 12 16 12 10 10
7 15 13 8 12 15
14 13 6 8 13 10
9 9 11 14 12 10
14 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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
Share on other sites
Quote:
Original post by nobodynews
my19937 is a typedef, at least in Visual C++


It is also per The Next Holy Standard:

Quote:
N3126=10-01 16

26.5.2 Header <random> Synopsis


[...]
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 this post


Link to post
Share on other sites
Quote:
Original post by Zahlman
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.

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]

Share this post


Link to post
Share on other sites

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

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this