// u использует e как источник чисел

 // каждый вызов возвращает однородно распределенное значение

 // в заданном диапазоне

 cout << u(e) << " ";

Вывод таков:

0 1 7 4 5 2 0 6 6 9

Здесь u определяется как объект типа uniform_int_distribution. Этот тип создает однородно распределенные беззнаковые значения. При определении объекта этого типа можно задать минимум и максимум необходимых значений. Определение u(0, 9) указывает, что необходимы числа в диапазоне от 0 до 9 включительно. Распределение случайного числа использует включающие диапазоны, позволяющие получить любое возможное целочисленное значение в нем.

Подобно типам процессоров, типы распределения также являются классами объектов функции. Типы распределения определяют оператор вызова, получающий процессор случайных чисел как аргумент. Объект распределения использует свой аргумент процессора для создания случайного числа, которое объект распределения сопоставит с определенным распределением.

Обратите внимание на то, что объект процессора передается непосредственно, u(e). Если бы вызов был написан как u(е()), то произошла бы попытка передать следующее созданное е значение в u, что привело бы к ошибке при компиляции. Поскольку некоторые распределения вызывают процессор несколько раз, передается сам процессор, а не очередной результат его вызова.

Когда упоминается генератор случайных чисел (random-number generator), имеется в виду комбинация объекта распределения с объектом процессора.

Сравнение процессора случайных чисел и функции rand()

Читатели, знакомые с библиотечной функцией rand() языка С, вероятно заметили, что вывод вызова объекта default_random_engine подобен выводу функции rand(). Процессоры предоставляют целые беззнаковые числа в определенном системой диапазоне. Функция rand() имеет диапазон от 0 до RAND_MAX. Диапазон процессора возвращается при вызове функций-членов min() и max() объекта его типа:

cout << "min: " << e.min() << " max: " << e.max() << endl;

На системе авторов эта программа выводит следующее

min: 1 max: 2147483646

Таблица 17.15. Операции с процессором случайного числа

Engine e;Стандартный конструктор; использует заданное по умолчанию начальное число для типа процессора
Engine e(s);Использует как начальное число целочисленное значение s
e.seed(s)Переустанавливает состояние процессора, используя начальное число s
e.min() e.max()Наименьшие и наибольшие числа, создаваемые данным генератором
Engine::result_typeЦелочисленный беззнаковый тип, создаваемый данным процессором
e.discard(u)Перемещает процессор на u шагов; u имеет тип unsigned long long
Процессоры создают последовательности чисел

У генераторов случайных чисел есть одно свойство, которое зачастую вызывает сомнения у новичков: даже при том, что создаваемые числа случайны, при каждом запуске данный генератор возвращает ту же последовательность чисел. Факт неизменности последовательности очень полезен во время проверки. С другой стороны, разработчики, использующие генераторы случайных чисел, должны учитывать этот факт.

Предположим, например, что необходима функция, создающая вектор из 100 случайных целых чисел, равномерно распределенных в диапазоне от 0 до 9. Могло бы показаться, что эту функцию следует написать следующим образом:

// безусловно неправильный способ создания

// вектора случайных целых чисел

// эта функция выводит те же 100 чисел при каждом вызове!

vector bad_randVec() {

 default_random_engine e;

 uniform_int_distribution u(0,9);

 vector ret;

 for (size_t i = 0; i < 100; ++i)

  ret.push_back(u(e));

 return ret;

}

Однако при каждом вызове эта функция возвратит тот же вектор:

vector v1(bad_randVec());

vector v2(bad_randVec());

// выводит equal

cout << ((v1 == v2) ? "equal" : "not equal") << endl;

Этот код выводит "equal", поскольку векторы v1 и v2 имеют те же значения.

Перейти на страницу:

Похожие книги