C++ - 在范围内生成遵循正态分布的随机数
C++ - generate random numbers following normal distribution within range
我需要生成遵循正态分布的随机数,该正态分布应位于 1000 和 11000 的区间内,平均值为 7000。我想使用 c++11 library function,但我不明白如何生成区间内的数字。有人可以帮忙吗?
您没有指定标准偏差。假设给定间隔的标准偏差为 2000,您可以尝试这样做:
#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;
}
可能的输出:
4520.53
6185.06
10224
7799.54
9765.6
7104.64
5191.71
10741.3
3679.14
5623.84
如果您只想指定 min
和 max
值,那么我们可以假设平均值为 (min + max) / 2
。我们还可以假设 min
和 max
与平均值相差 3 个标准差。通过这些设置,我们将仅丢弃 0.3% 的生成值。所以你可以添加以下构造函数:
Generator(double min, double max):
distribution((min + max) / 2, (max - min) / 6), min(min), max(max)
{}
并将生成器初始化为:
Generator g(1000.0, 11000.0);
正态分布由两个数字决定:均值和方差。 (参见 Wikipedia)。你可以限制输出,但它不再是正态分布。如果标准偏差远小于您的间隔,则这种差异是微不足道的。处理它的一种方法是拉一个随机数,如果它在区间之外,则将其固定到区间边缘。这会在你的时间间隔的边缘放置很少的概率尖峰。数学上更好的方法(尽管在计算上可能很糟糕)是丢弃区间外的任何值并绘制另一个值。这具有截断分布而不改变其形状(规范化除外)的效果。以下是您可以如何做到这一点。我没测试。
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 )
在这里您可以找到随机数生成器的库:
http://www.agner.org/random/?e=0,31
例如,截断正态分布在 stocc 库中实现:
http://www.agner.org/random/stocc.zip
我需要生成遵循正态分布的随机数,该正态分布应位于 1000 和 11000 的区间内,平均值为 7000。我想使用 c++11 library function,但我不明白如何生成区间内的数字。有人可以帮忙吗?
您没有指定标准偏差。假设给定间隔的标准偏差为 2000,您可以尝试这样做:
#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;
}
可能的输出:
4520.53
6185.06
10224
7799.54
9765.6
7104.64
5191.71
10741.3
3679.14
5623.84
如果您只想指定 min
和 max
值,那么我们可以假设平均值为 (min + max) / 2
。我们还可以假设 min
和 max
与平均值相差 3 个标准差。通过这些设置,我们将仅丢弃 0.3% 的生成值。所以你可以添加以下构造函数:
Generator(double min, double max):
distribution((min + max) / 2, (max - min) / 6), min(min), max(max)
{}
并将生成器初始化为:
Generator g(1000.0, 11000.0);
正态分布由两个数字决定:均值和方差。 (参见 Wikipedia)。你可以限制输出,但它不再是正态分布。如果标准偏差远小于您的间隔,则这种差异是微不足道的。处理它的一种方法是拉一个随机数,如果它在区间之外,则将其固定到区间边缘。这会在你的时间间隔的边缘放置很少的概率尖峰。数学上更好的方法(尽管在计算上可能很糟糕)是丢弃区间外的任何值并绘制另一个值。这具有截断分布而不改变其形状(规范化除外)的效果。以下是您可以如何做到这一点。我没测试。
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 )
在这里您可以找到随机数生成器的库: http://www.agner.org/random/?e=0,31 例如,截断正态分布在 stocc 库中实现: http://www.agner.org/random/stocc.zip