Worldtreeboy wrote: |
---|
Let's say I have I need to generate 100 numbers with minimum value of 0 and maximum value of 1440. The mean of the 100 numbers is 150 and the standard deviation is 25. |
George P wrote: |
---|
Specifically look at what std::normal_distribution offers, mean and standard deviation are selectable. |
When you mention "mean" and "standard deviation" it certainly sounds like you would want a normal distribution.
1 2 3 4 5 6 7
|
std::mt19937 rng{std::random_device()()};
std::normal_distribution<> dist(150, 25);
for (int i = 0; i < 100; ++i)
{
int n = std::round(dist(rng));
std::cout << n << "\n";
}
| |
But the question is how do we limit it? The range of a normal distribution is unlimited.
If you just clamp the values ...
|
int n = std::clamp<int>(std::round(dist(rng)), 0, 1440);
| |
... you'll get an unproportionate number of values that are equal to the max and min values (especially the min in this case).
Another approach is to keep generating a new number until you get one that is within the range ...
1 2 3 4 5
|
int n;
do
{
n = std::round(dist(rng));
} while (n < 0 || n > 1440);
| |
... but this skews the mean and standard deviation. In this case the mean would be slightly larger than 150. If only a small proportion of all values fall outside the range then it might not matter, depending on the application.
To avoid affecting the mean you could make sure to regenerate the numbers so that they stay on the same side of the mean...
1 2 3 4 5 6 7 8 9
|
int n = std::round(dist(rng));
if (n < 0)
n = std::uniform_int_distribution<>(0, 150)(rng);
}
else if (n > 1440)
{
n = std::uniform_int_distribution<>(150, 1440)(rng);
}
| |
...but this will obviously affect the standard deviation. Note that the above is just one of many different ways to do it. Another way might affect the standard deviation differently.
I think you could also calculate how big proportion that falls outside the range at both ends and adjust the mean of the std::normal_distribution in a way that the do-while method gives you the intended mean but I'm not too good at this kind of math so I'm not sure. Perhaps you could adjust both the mean and the standard deviation so that the do-while method gives you both the mean and the standard deviation as intended but note that if you plotted the probability density function you might no longer get the peak of the graph where the mean is because the graph is no longer symmetrical like a normal distribution is.
If you're just doing a game or something you can probably just approximate it, with a std::normal_distribution as I did above, or some other non-exact method, and then test it and adjust it until you are satisfied. Otherwise, if you need it to be mathematically correct you probably need a better understanding of the math than I have, to understand what you really want, and to be able ensure that you get it right.