Generating random integers in c++ - c++

I am trying to generate a random number in c++ using a modern approach.However i get the same random number every time i call the function
int getRandomPixel() {
std::random_device rd; // obtain a random number from hardware
std::mt19937 eng(rd()); // seed the generator
std::uniform_int_distribution<> distr(0, 255); // define the range
return distr(eng);
}

Your std::random_device is a PRNG, as stated on cppreference:
std::random_device may be implemented in terms of an
implementation-defined pseudo-random number engine if a
non-deterministic source (e.g. a hardware device) is not available to
the implementation. In this case each std::random_device object may
generate the same number sequence.
On each call of getRandomPixel() you recreate the rd which will then produce the same first seed each time which will in turn produce the same value when your mt19937 is seeded with that value because that's recreated as well and thus has the same initial state.
You should not recreate them each call:
int getRandomPixel() {
static std::random_device rd; // obtain a random number from hardware
static std::mt19937 eng(rd()); // seed the generator
static std::uniform_int_distribution<> distr(0, 255); // define the range
return distr(eng);
}

The following solves the problem.I believe the issue was that i was recreating the device and the generator in every call
using u16 = unsigned short int;
u16 getRandomPixel() {
static std::random_device rd; // obtain a random number from hardware
static std::mt19937 eng(rd()); // seed the generator
std::uniform_int_distribution<u16> distr(0, 255); // define the range
return distr(eng);
}

Related

Proper way to generate random long long?

I am trying to generate random long long numbers using this code in C++:
random_device rd;
default_random_engine gen(rd());
uniform_int_distribution<long long> distribution(1, llround(pow(10, 12)));
long long random_num = distribution(gen);
I just want to verify that this should generate random integers from [1, 10^12] uniformly. Is this the correct way to do it?
EDIT:
random_device rd;
mt19937_64 gen(rd());
uniform_int_distribution<long long> distribution(1, llround(pow(10, 12)));
long long random_num = distribution(gen);
Combining all the comments above,
Prefer std::mt19937 or std::mt19937_64 to std::default_random_engine to get high-quality random numbers. You can use both generators with std::uniform_int_distribution. Distributions know how to manage generators whose output range is smaller then the target range.
Instead of std::llround(std::pow(10, 12)) prefer the compile-time constant (1'000'000'000'000LL). In general, not every integer can be represented exactly, and you might get unexpected results. For example, std::llround(std::pow(9, 17)) gives 16677181699666568, whereas the 9^17 = 16677181699666569.
Seeding a generator with a single number (typically, 32-bit), std::mt19937_64 gen(rd()), is the simplest thing you can do. In some situations you might want to use more bits of entropy, i.e. not just a single number, but a seed sequence. See this question for more details.

How to Understand C++11 random number generator

Those three lines of generating random number looks a bit tricky. It is hard to always remember those lines. Could someone please shed some light on it to make it easier to understand?
#include <random>
#include <iostream>
int main()
{
std::random_device rd; //1st line: Will be used to obtain a seed for the random number engine
std::mt19937 gen(rd()); //2nd line: Standard mersenne_twister_engine seeded with rd()
std::uniform_int_distribution<> dis(1, 6);
for (int n=0; n<10; ++n)
std::cout << dis(gen) << ' '; //3rd line: Use dis to transform the random unsigned int generated by gen into an int in [1, 6]
std::cout << '\n';
}
Here are some questions I can think of:
1st line of code:
random_device is a class as described by the documentation random_device, so this line means declaring a object rd? If yes, why in 2nd line we pass rd() to construct mt19937 instead of using the object rd (without parentheses)?
3rd line of code:
Why do call class uniform_int_distribution<> object dis()? Is dis() a function? Why shall we pass in gen object into dis()?
random_device is slow but genuinely random, it's used to generate the 'seed' for the random number sequence.
mt19937 is fast but only 'pseudo random'. It needs a 'seed' to start generating a sequence of numbers. That seed can be random (as in your example) so you get a different sequence of random numbers each time. But it could be a constant, so you get the same sequence of numbers each time.
uniform_int_distribution is a way of mapping random numbers (which could have any values) to the numbers you're actually interested in, in this case a uniform distribution of integers from 1 to 6.
As is often the case with OO programming, this code is about division of responsibilities. Each class contributes a small piece to the overall requirement (the generation of dice rolls). If you wanted to do something different it's easy because you've got all the pieces in front of you.
If this is too much then all you need to do is write a function to capture the overall effect, for instance
int dice_roll()
{
static std::random_device rd;
static std::mt19937 gen(rd());
static std::uniform_int_distribution<> dis(1, 6);
return dis(gen);
}
dis is an example of a function object or functor. It's an object which overloads operator() so it can be called as if it was a function.
std::random_device rd; // create access to truly random numbers
std::mt19937 gen{rd()}; // create pseudo random generator.
// initialize its seed to truly random number.
std::uniform_int_distribution<> dis{1, 6}; // define distribution
...
auto x = dis(gen); // generate pseudo random number form `gen`
// and transform its result to desired distribution `dis`.

Using same random number generator across multiple functions

I am given to believe that random number generators (RNGs) should only be seeded once to ensure that the distribution of results is as intended.
I am writing a Monte Carlo simulation in C++ which consists of a main function ("A") calling another function ("B") several times, where a large quantity of random numbers is generated in B.
Currently, I am doing the following in B:
void B(){
std::array<int, std::mt19937::state_size> seed_data;
std::random_device r;
std::generate(seed_data.begin(), seed_data.end(), std::ref(r));
std::seed_seq seq(std::begin(seed_data), std::end(seed_data)); //perform warmup
std::mt19937 eng(seq);
std::uniform_real_distribution<> randU(0,1);
double myRandNum = randU(eng);
//do stuff with my random number
}
As you can see, I am creating a new random number generator each time I call the function B. This, as far as I can see, is a waste of time - the RNG can still generate a lot more random numbers!
I have experimented with making "eng" extern but this generates an error using g++:
error: ‘eng’ has both ‘extern’ and initializer extern std::mt19937 eng(seq);
How can I make the random number generator "global" so that I can use it many times?
Be careful with one-size-fits-all rules. 'Globals are evil' is one of them. A RNG should be a global object. (Caveat: each thread should get its own RNG!) I tend to wrap mine in a singleton map, but simply seeding and warming one up at the beginning of main() suffices:
std::mt19937 rng;
int main()
{
// (seed global object 'rng' here)
rng.dispose(10000); // warm it up
For your usage scenario (generating multiple RNs per call), you shouldn't have any problem creating a local distribution for each function call.
One other thing: std::random_device is not your friend -- it can throw at any time for all kinds of stupid reasons. Make sure to wrap it up in a try..catch block. Or, and I recommend this, use a platform specific way to get a true random number. (On Windows, use the Crypto API. On everything else, use /dev/urandom/.)
Hope this helps.
You shouldn't need to pass anything or declare anything, as the interaction between mt19937 and uniform_real_distribution is through globals.
std::array<int, std::mt19937::state_size> seed_data;
std::random_device r;
std::generate(seed_data.begin(), seed_data.end(), std::ref(r));
std::seed_seq seq(std::begin(seed_data), std::end(seed_data)); //perform warmup
std::mt19937 eng(seq);
B()
...
void B()
{
std::uniform_real_distribution<> randU(0,1);
...

Generating number (0,1) using mersenne twister c++

I'm working on implementing R code into C++ so that it runs faster, but I am having difficulties implementing mersenne twister. I only wish to generate values between (0,1). Here is what I have that pertains to this question.
#include <random>
std::mt19937 generator (123);
std::cout << "Random value: " << generator() << std:: endl;
I tried dividing by RAND_MAX, but that did not produce the values that I was looking for.
Thanks in advance.
In C++11 the concepts of "(pseudo) random generator" and "probability distribution" are separated, and for good reasons.
What you want can be achieved with the following lines:
std::mt19937 generator (123);
std::uniform_real_distribution<double> dis(0.0, 1.0);
double randomRealBetweenZeroAndOne = dis(generator);
If you want to understand why this separation is necessary, and why using a standard division /range manipulation on the output of the generator is a bad idea, watch this video.
You may want to consider code like this:
// For pseudo-random number generators and distributions
#include <random>
...
// Use random_device to generate a seed for Mersenne twister engine.
std::random_device rd{};
// Use Mersenne twister engine to generate pseudo-random numbers.
std::mt19937 engine{rd()};
// "Filter" MT engine's output to generate pseudo-random double values,
// **uniformly distributed** on the closed interval [0, 1].
// (Note that the range is [inclusive, inclusive].)
std::uniform_real_distribution<double> dist{0.0, 1.0};
// Generate pseudo-random number.
double x = dist(engine);
For more details on generating pseudo-random numbers in C++ (including reasons why rand() is not good), see this video by Stephan T. Lavavej (from Going Native 2013):
rand() Considered Harmful
std::mt19937 does not generate between 0 and RAND_MAX like rand(), but between 0 and 2^32-1
And by the way, the class provides min() and max() values!
You need to convert the value to a double, substract min() and divide by max()-min()
uint32_t val;
val << generator;
double doubleval = ((double)val - generator::min())/(generator::max()-generator::min());
or (less generic)
uint32_t val;
val << generator;
double doubleval = (double)val * (1.0 / std::numeric_limits<std::uint32_t>::max());

Uncorrelated parallel random seeds with C++ 2011?

Currently, I have a main application in Fortran that need a seed to generate pseudo-random numbers.
I would like to run many (many) times this application with completely uncorrelated seeds (and furthermore completely independent pseudo-random numbers chains).
My question is : how to generate the seeds with C++ 2011 ?
In your main thread, extract a single seed (or seed sequence) from a good random source (e.g. from /dev/urandom on Linux). Use that data to seed a single root PRNG. Then use that PRNG to generate seed values for your thread-local PRNGs.
#include <random>
#include <vector>
typedef std::mt19937 rng_type;
std::uniform_int_distribution<rng_type::result_type> udist;
int main()
{
rng_type rng;
// seed rng first, and store the result in a log file:
rng_type::result_type const root_seed = get_seed();
rng.seed(root_seed);
// make thread seeds:
std::vector<rng_type::result_type> seeds(NUMBER_OF_THREADS);
for (auto & n : seeds) { n = udist(rng); }
// make threads...
}
The random number engine interface in <random> lets you seed both from a single integer and from a sequence of integers. If you want additional randomness, you can seed the mt19937 from a sequence of several hundred integers.
C++11 provides std::random_device to provide non-deterministic random numbers if a source is available. You'll have to check your implementation to be sure it's good though. libc++ uses /dev/urandom by default. libstdc++ does as well if the macro _GLIBCXX_USE_RANDOM_TR1 is defined. Visual Studio's implementation is unfortunately not non-deterministic. edit: as of VS2012 their implementation uses Windows' cryptography services.
If std::random_device provides access to a non-deterministic source of randomness (typically /dev/urandom uses a cryptographic PRNG) then this should be sufficient for generating independent seeds.
#include <random>
int main() {
std::random_device r;
std::seed_seq seed{r(), r(), r(), r(), r(), r(), r(), r()};
std::mt19937 engine(seed);
}
Instead of using a single value as a seed, some engines may do better with more seed data. A seed sequence is the alternative provided by the standard. Engines can be seeded with seed sequences, which are objects you load up with any amount of data and which produces seed data based on that.
std::random_device r;
std::vector<std::mt19937> engines;
int engines = 50;
for (int i = 0; i < engines; ++i) {
std::seed_seq s{r(), r(), r(), r(), r(), r(), r(), r()};
engines.emplace_back(s);
}
Eight 32-bit values, 256 bits, is enough but if you really want you can use more. Each of the standard engines documents how much data it uses from a seed sequence.
For example, each mt19937 engine will retrieve mt19937::state_size (624) 32-bit values from the seed sequence. The seeds retrieved from the seed sequence aren't the same as the input data, but they're based on that data, so we can use that much random data in the sequence.
std::random_device r;
std::vector<std::uint_least32_t> data;
std::generate_n(back_inserter(data), 624, std::ref(r));
std::seed_seq seed(begin(data), end(data));
std::mt19937 engine(seed); // 'fully' seeded mt19937
You can't ever really generate random seeds. You pull them from somewhere. The OS likely has a way to retrieve pseudorandom values (/dev/urandom on Linux, for example) which can be used to seed.
Getting a timestamp representing the current time is also a common option -- then to ensure you get different seeds for each thread, just make sure they ask for the timestamp at slightly different times, and use a high-resolution timer to ensure they actually get different values as seeds.
There's no "get a good seed" function built into C++11, because such a function is essentially meaningless. The computer can't generate random data. You have to pick something that looks random enough for your purposes, and use that to seed the random generator