Right now I use the following code to create a uniform distribution of integers with a range. (I took out the seeding code)
int random(int min, int max)
{
static std::mt19937 gen;
std::uniform_int<int> dist(min, max);
return dist(gen);
}
I am trying to modify it to give a distribution that favors twords the min value, and almost never produces nears the max value. I can see all of the pre-made distributions, but none of them are integer. And also I can't tell which one fits my needs based on any of the documentation. The closest I have come is the chi squared distribution as shown on wikipedia, where k=2
But I can't figure out, based on the documentation how to use it with integers, let alone set the k value.
How can I set up my function to use an appropriate non-uniform, integer distribution?
still working on choosing the correct distro: here are the results of std::poisson_distribution<int> dist((max - min) * .1);
from 0 to 20:
not quite there yet, as 0 should be more frequent than 1, but it should help the next person out, will post more results as they come.
well my final solution became a combination of methods:
int randomDist(int min, int max)
{
static std::mt19937 gen;
std::chi_squared_distribution<double> dist(2);
int x;
do
{
x = (int)(max*dist(gen)/10) + min;
}
while (x > max);
return x;
}
giving the result of:
If u is a uniform random number on (0,1), then x = F - 1 ( u ) generates a random number x from any continuous distribution with the specified cdf F .
Non-uniform random variate generation or pseudo-random number sampling is the numerical practice of generating pseudo-random numbers (PRN) that follow a given probability distribution. Methods are typically based on the availability of a uniformly distributed PRN generator.
Generating an exponential distribution random variable can be done by: -ln(U)/lambda (where U~Uniform(0,1)). In exponential distribution: lamda = 1/mean , so it gets you: myVar = -ln(U) * mean (where U~Uniform(0,1)).
The uniform distribution is the underlying distribution for an uniform random variable. A continuous uniform random variable, denoted as , take continuous values within a given interval. , with equal probability. Therefore, the PDF of such a random variable is a constant over the given interval is.
There are other integer distributions there, they just don't have int
in their names. They do have typedef IntType result_type
in their class definitions.
The ones which behave as you describe are:
binomial_distribution
(t, p)
This generates numbers in the range 0 ≤ x ≤ t, so you need to translate the range by min
. The mean is at t·p, so choose a p near 0.
std::binomial_distribution<int> dist(max - min, .1);
return dist(gen) + min;
poisson_distribution
(λ)
This generates numbers 0 ≤ x < ∞, but large numbers are progressively less likely. You can censor anything above max
to limit it to a range. The parameter λ is the mean. Choosing it to match the previous example:
std::poisson_distribution<int> dist((max - min) * .1);
int x;
do
x = dist(gen) + min;
while (x > max);
return x;
geometric_distribution
(p)
Also generates numbers 0 ≤ x < ∞, but 0 is the most likely outcome and every subsequent number is less likely than the previous. Again choosing the parameter to match the mean of the previous example:
std::geometric_distribution<int> dist(1 / ((max - min) * .1 + 1));
int x;
do
x = dist(gen) + min;
while (x > max);
return x;
You can also use any of the continuous distributions to generate a double
and then round it to an int
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With