Создание гауссовского генератора случайных чисел со средним и стандартным отклонением

Я пытаюсь создать одномерный массив и использовать генератор случайных чисел (генератор Гаусса, который генерирует случайное число со средним значением 70 и стандартным отклонением 10), чтобы заполнить массив не менее чем 100 числами от 0 до 100 включительно.

Как я буду делать это в C ++?

14

Решение

В C ++ 11 это относительно просто, используя случайный заголовок а также станд :: normal_distribution (живой пример):

#include <iostream>
#include <iomanip>
#include <string>
#include <map>
#include <random>

int main()
{
std::random_device rd;

std::mt19937 e2(rd());

std::normal_distribution<> dist(70, 10);

std::map<int, int> hist;
for (int n = 0; n < 100000; ++n) {
++hist[std::round(dist(e2))];
}

for (auto p : hist) {
std::cout << std::fixed << std::setprecision(1) << std::setw(2)
<< p.first << ' ' << std::string(p.second/200, '*') << '\n';
}
}

Если C ++ 11 не вариант, чем увеличение также предоставляет библиотеку (живой пример):

#include <iostream>
#include <iomanip>
#include <string>
#include <map>
#include <random>
#include <boost/random.hpp>
#include <boost/random/normal_distribution.hpp>

int main()
{

boost::mt19937 *rng = new boost::mt19937();
rng->seed(time(NULL));

boost::normal_distribution<> distribution(70, 10);
boost::variate_generator< boost::mt19937, boost::normal_distribution<> > dist(*rng, distribution);

std::map<int, int> hist;
for (int n = 0; n < 100000; ++n) {
++hist[std::round(dist())];
}

for (auto p : hist) {
std::cout << std::fixed << std::setprecision(1) << std::setw(2)
<< p.first << ' ' << std::string(p.second/200, '*') << '\n';
}
}

и если по какой-либо причине ни один из этих вариантов невозможен, вы можете свернуть свой собственный Преобразование Бокса-Мюллера, код, указанный в ссылке, выглядит разумно.

25

Другие решения

Используйте дистрибутив Box Muller (из Вот):

double rand_normal(double mean, double stddev)
{//Box muller method
static double n2 = 0.0;
static int n2_cached = 0;
if (!n2_cached)
{
double x, y, r;
do
{
x = 2.0*rand()/RAND_MAX - 1;
y = 2.0*rand()/RAND_MAX - 1;

r = x*x + y*y;
}
while (r == 0.0 || r > 1.0);
{
double d = sqrt(-2.0*log(r)/r);
double n1 = x*d;
n2 = y*d;
double result = n1*stddev + mean;
n2_cached = 1;
return result;
}
}
else
{
n2_cached = 0;
return n2*stddev + mean;
}
}

Вы можете прочитать больше на: Вольфраме математический мир

6

С #include <random>

std::default_random_engine de(time(0)); //seed
std::normal_distribution<int> nd(70, 10); //mean followed by stdiv
int rarrary [101]; // [0, 100]
for(int i = 0; i < 101; ++i){
rarray[i] = nd(de); //Generate numbers;
}
2

В C ++ 11 вы будете использовать средства, предоставляемые <random> заголовок; создать случайный двигатель (например, std::default_random_engine или же std::mt19937, инициализируется с std::random_device при необходимости) и std::normal_distribution объект инициализирован с вашими параметрами; тогда вы можете использовать их вместе, чтобы генерировать свои номера. Вот Вы можете найти полный пример.

В предыдущих версиях C ++ вместо этого все, что у вас есть, это «классический» C LCG (srand/rand), который просто генерирует простое целочисленное распределение в диапазоне [0, MAX_RAND]; с его помощью вы все еще можете генерировать гауссовские случайные числа, используя Преобразование Бокса-Мюллера. (Может быть полезно отметить, что C ++ 11 GNU GCC libstdc ++ std::normal_distribution использует Марсалья полярный метод как показано здесь.).

2
По вопросам рекламы [email protected]