}
return value;
}
11.6. Генерация случайных чисел
Требуется сгенерировать несколько случайных чисел в формате с плавающей точкой в интервале значений [0.0, 1.0)
при равномерном их распределении.
Стандарт C++ предусматривает наличие C-функции библиотеки этапа исполнения rand
, определенной в заголовочном файле <cstdlib>
, которая возвращает случайное число в диапазоне от 0 до RAND_MAX
включительно. Макропеременная RAND_MAX
представляет собой максимальное значение, которое может быть возвращено функцией rand
. Пример 11.11 демонстрирует применение функции rand
для генерации случайных чисел с плавающей точкой.
#include <cstdlib>
#include <ctime>
#include <iostream>
using namespace std;
double doubleRand() {
return double(rand()) / (double(RAND_MAX) + 1.0);
}
int main() {
srand(static_cast<unsigned int>(clock()));
cout << 'expect 5 numbers within the interval [0.0, 1.0)' << endl;
for (int i=0; i < 5; i++) {
cout << doubleRand() << '
';
}
cout << endl;
}
Программа примера 11.11 должна выдать результат, подобный следующему.
expect 5 numbers within the interval [0.0, 1.0)
0.010437
0.740997
0.34906
0.369293
0.544373
Необходимо уточнить, что функции, генерирующие случайные числа (в том числе rand
), возвращают псевдослучайные числа, а не реальные случайные числа, поэтому там, где я говорю «случайное число», я на самом деле имею в виду псевдослучайное число.
Перед применением функции rand
вы должны «посеять» (т.е. инициализировать) генератор случайных чисел с помощью вызова функции srand
. Это обеспечивает генерацию последующими вызовами rand
разных последовательностей чисел при каждом новом исполнении программы. Проще всего инициализировать генератор случайных чисел путем передачи ему результата вызова функции clock
из заголовочного файла <ctime>
, имеющего тип unsigned int
. Повторная инициализация генератора случайных чисел приводит к тому, что генерируемые числа становятся менее случайными.
Функция rand
имеет много ограничений. Прежде всего, она генерирует только целые числа, и эти числа могут иметь только равномерное распределение. Более того, конкретный алгоритм генерации случайных чисел зависит от реализации, и поэтому последовательности случайных чисел нельзя воспроизвести при переходе от одной системы к другой при одинаковой инициализации. Это создает трудности для определенного типа приложений, а также при тестировании и отладке.
Значительно более изощренную альтернативу rand
представляет написанная Джензом Маурером (Jens Maurer) библиотека Boost Random; она была инспирирована предложениями по генерации случайных чисел, представленными в TR1.
TR1 означает «Technical Report One» и представляет собой официальный проект по расширению стандартной библиотеки C++98.
Библиотека Boost Random содержит несколько высококачественных функций по генерации случайных чисел как для целых типов, так и для типов с плавающей точкой, причем с поддержкой многочисленных распределений. Пример 11.12 показывает, как можно сгенерировать случайные числа с плавающей точкой в интервале значений [0,1)
.
#include <boost/random.hpp>
#include <iostream>
#include <cstdlib>
using namespace std;
using namespace boost;
typedef boost::mt19937 BaseGenerator;
typedef boost::uniform_real<double> Distribution;
typedef boost::variate_generator<BaseGenerator, Distribution> Generator;
double boostDoubleRand() {
static BaseGenerator base;
static Distribution dist;
static Generator rng(base, dist);
return rng();
}
int main() {
cout << 'expect 5 numbers within the interval [0.1)' << endl;
for (int i=0; i < 5; i++) {
cout << boostDoubleRand() << '
';
}
cout << endl;
}
Основное преимущество библиотеки Boost Random в том, что алгоритм генерации псевдослучайных чисел обеспечивает гарантированные и воспроизводимые свойства случайных последовательностей,