I need to generate random numbers that follow a normal distribution which should lie within the interval of 1000 and 11000 with a mean of 7000. I want to use the c++11 library function but I am not understanding how to generate the numbers within the interval. Can someone help?
问题:
回答1:
You don't specify the standard deviation. Assuming a standard deviation of 2000 for the given interval you can try this:
#include <iostream>
#include <random>
class Generator {
std::default_random_engine generator;
std::normal_distribution<double> distribution;
double min;
double max;
public:
Generator(double mean, double stddev, double min, double max):
distribution(mean, stddev), min(min), max(max)
{}
double operator ()() {
while (true) {
double number = this->distribution(generator);
if (number >= this->min && number <= this->max)
return number;
}
}
};
int main() {
Generator g(7000.0, 2000.0, 1000.0, 11000.0);
for (int i = 0; i < 10; i++)
std::cout << g() << std::endl;
}
Possible output:
4520.53
6185.06
10224
7799.54
9765.6
7104.64
5191.71
10741.3
3679.14
5623.84
If you want to specify only the min
and max
values, then we can assume that the mean value is (min + max) / 2
. Also we can assume that min
and max
are 3 standard deviations away from the mean value. With these settings we are going to throw away only 0.3% of the generated values. So you can add the following constructor:
Generator(double min, double max):
distribution((min + max) / 2, (max - min) / 6), min(min), max(max)
{}
and initialize the generator as:
Generator g(1000.0, 11000.0);
回答2:
A normal distribution is determined by two numbers: a mean, and a variance. (see Wikipedia). You can limit the output, but it is no longer a normal distribution. If the standard deviation is much smaller than your interval this difference is trivial. One way to handle it is to pull a random number and if it is outside the interval fix it to the interval edge. This would put little spikes of probability at the edge of your intervals. A better way mathematically (although potentially bad computationally) is to throw out any value outside the interval and draw another one. This has the effect of truncating your distribution without changing it's shape (other than a normalization). Here is how you might do that. I didn't test it.
std::default_random_engine generator;
std::normal_distribution<double> distribution(7000.0,100.0);
double sample;
do{
sample= distribution(generator);
}while( sample<1000.0 || sample>11000.0 )
回答3:
Here you can find libraries for random number generators: http://www.agner.org/random/?e=0,31 For instance, truncated normal distribution is implemented in stocc library: http://www.agner.org/random/stocc.zip