Мне нужно генерировать случайные числа, которые следуют нормальному распределению, которое должно лежать в интервале от 1000 до 11000 со средним значением 7000. Я хочу использовать библиотечная функция c ++ 11 но я не понимаю, как генерировать числа в пределах интервала. Может кто-нибудь помочь?
Вы не указываете стандартное отклонение. Предполагая стандартное отклонение 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);
Нормальное распределение определяется двумя числами: средним и дисперсией. (увидеть Википедия). Вы можете ограничить вывод, но он больше не является нормальным распределением. Если стандартное отклонение намного меньше вашего интервала, эта разница тривиальна. Один из способов справиться с этим — вывести случайное число и, если оно выходит за пределы интервала, зафиксировать его на границе интервала. Это поместило бы небольшие всплески вероятности на границе ваших интервалов. Лучший математический способ (хотя потенциально плохой в вычислительном отношении) состоит в том, чтобы выбросить любое значение вне интервала и нарисовать другое. Это приводит к усечению вашего дистрибутива без изменения его формы (кроме нормализации). Вот как вы можете это сделать. Я не проверял это.
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