Для примера создадим серию нормально распределенных значений и нарисуем полученное распределение. Поскольку тип normal_distribution
создает числа с плавающей запятой, данная программа будет использовать функцию lround()
из заголовка cmath
для округления каждого результата до ближайшего целого числа. Создадим 200 чисел с центром в значении 4 и среднеквадратичным отклонением 1,5. Поскольку используется нормальное распределение, можно ожидать любых чисел, но приблизительно 1% из них будет в диапазоне от 0 до 8 включительно. Программа подсчитает, сколько значений соответствует каждому целому числу в этом диапазоне:
default_random_engine е; //
normal_distribution<> n(4,1.5); //
//
vector
for (size_t i = 0; i != 200; ++i) {
unsigned v = lround(n(e)); //
if (v < vals.size()) //
++vals[v]; // подсчитать, как часто встречается каждое число
}
for (size_t j = 0; j != vals.size(); ++j)
cout << j << ": " << string(vals[j], '*') << endl;
Начнем с определения объектов генератора случайных чисел и вектора vals
. Вектор vals
будет использован для расчета частоты создания каждого числа в диапазоне 0…9. В отличие от большинства других программ, использующих вектор, создадим его сразу с необходимым размером. Так, каждый его элемент инициализируется значением 0.
В цикле for
происходит вызов функции lround(n(е))
для округления возвращенного вызовом n(е)
значения до ближайшего целого числа. Получив целое число, соответствующее случайному числу с плавающей точкой, используем его для индексирования вектора счетчиков. Поскольку вызов n(е)
может создавать числа и вне диапазона от 0 до 9, проверим полученное число на принадлежность диапазону прежде, чем использовать его для индексирования вектора vals
. Если число принадлежит диапазону, увеличиваем соответствующий счетчик.
Когда цикл заканчивается, вывод содержимого вектора vals
выглядит следующим образом:
0: ***
1: ********
2: ********************
3: **************************************
4: **********************************************************
5: ******************************************
6: ***********************
7: *******
8: *
Выведенные строки содержат столько звездочек, сколько раз встретилось соответствующее значение, созданное генератором случайных чисел. Обратите внимание: эта фигура не совершенно симметрична. Если бы она была симметрична, то возникли бы подозрения в качестве генератора случайных чисел.
bernoulli_distribution
Как уже упоминалось, есть одно распределение, которое не получает параметр шаблона. Это распределение bernoulli_distribution
, являющееся обычным классом, а не шаблоном. Это распределение всегда возвращает логическое значение true
с заданной вероятностью. По умолчанию это вероятность .5.
В качестве примера распределения этого вида напишем программу, которая играет с пользователем. Игру начинает один из игроков (пользователь или программа). Чтобы выбрать первого игрока, можно использовать объект класса uniform_int_distribution
с диапазоном от 0 до 1. В качестве альтернативы этот выбор можно сделать, используя распределение Бернулли. С учетом, что игру начинает функция play()
, для взаимодействия с пользователем может быть использован следующий цикл:
string resp;
default_random_engine e; //
//
bernoulli_distribution b; // по умолчанию четность 50/50
do {
bool first = b(e); //
cout << (first ? "We go first"
: "You get to go first") << endl;
//
cout << ((play(first)) ? "sorry, you lost"
: "congrats, you won") << endl;