- Фантастика и фэнтези
- Ироническое фэнтези
- Стимпанк
- Детективная фантастика
- Киберпанк
- Попаданцы
- LitRPG
- Космоопера
- Технофэнтези
- Городская фантастика
- Русское фэнтези
- Юмористическая фантастика
- Космическая фантастика
- Боевое фэнтези
- Эпическая фантастика
- Зарубежная фантастика
- Книги магов
- Мистика
- Разная фантастика
- Разное фэнтези
- Любовное фэнтези
- Романтическая фантастика
- Городское фентези
- Историческая фантастика
- Историческое фэнтези
- Социально-философская фантастика
- Сказочная фантастика
- Иностранное фэнтези
- Романтическое фэнтези
- Ироническая фантастика
- Ужасы и Мистика
- Постапокалипсис
- Героическая фантастика
- Фэнтези
- Научная Фантастика
- Социально-психологическая
- Альтернативная история
- Боевая фантастика
- Разная литература
- Пословицы, поговорки
- Шахматы
- Визуальные искусства
- Фанфик
- Авто и ПДД
- Военное
- Отраслевые издания
- Гиды, путеводители
- Зарубежная образовательная литература
- Военная история
- Цитаты из афоризмов
- Современная литература
- Великолепные истории
- Начинающие авторы
- Современная зарубежная литература
- Боевые искусства
- Изобразительное искусство, фотография
- Кино
- Литература 19 века
- Недвижимость
- Музыка, музыканты
- Готические новеллы
- Истории из жизни
- Культура и искусство
- Спецслужбы
- Зарубежная прикладная литература
- Музыка, танцы
- Подростковая литература
- Прочее
- Военная техника, оружие
- Газеты и журналы
- Периодические издания
- Домоводство, Дом и семья
- Любовные романы
- Экономическая литература
- Научные и научно-популярные книги
- О животных
- Биохимия
- Культурология
- Юриспруденция
- Политика
- Психотерапия
- Языкознание
- Научпоп
- Медицина
- Психология, личное
- Радиотехника
- Филология
- Педагогика
- Образовательная литература
- Деловая литература
- Физика
- Науки: разное
- Химия
- Воспитание детей, педагогика
- Детская психология
- Зарубежная публицистика
- Биология
- Архитектура
- Зарубежная психология
- Науки о космосе
- Социология
- Математика
- География
- Беременность, ожидание детей
- Литературоведение
- Транспорт, военная техника
- Обществознание
- Зоология
- География
- Альтернативная медицина
- Иностранные языки
- Ветеринария
- Рефераты
- Астрология
- Биофизика
- Экология
- История Европы
- Учебники
- Шпаргалки
- Государство и право
- Ботаника
- Религиоведение
- История
- Техническая литература
- Прочая научная литература
- Психология
- Детективы и Триллеры
- Справочная литература
- Проза
- Новелла
- Юмор
- Проза
- Историческая проза
- Русская современная проза
- Советская классическая проза
- Повести
- Очерки
- Эссе
- Рассказы
- Зарубежная современная проза
- Сентиментальная проза
- Зарубежная классика
- Афоризмы
- Эпистолярная проза
- Феерия
- Семейный роман/Семейная сага
- Разное
- Антисоветская литература
- Магический реализм
- Русская классическая проза
- Современная проза
- О войне
- Контркультура
- Классическая проза
- Поэзия, Драматургия
- Детская литература
- Детская фантастика
- Детские остросюжетные
- Детские стихи
- Детские приключения
- Внеклассное чтение
- Учебная литература
- Зарубежные детские книги
- Бизнес
- Загадки
- Книги для подростков
- Школьные учебники
- Детский фольклор
- Книги для дошкольников
- Детские детективы
- Детская познавательная и развивающая литература
- Буквари
- Прочая детская литература
- Сказка
- Детская проза
- Детская образовательная литература
- Юмор
- Документальные книги
- Бизнес
- Внешнеэкономическая деятельность
- Тайм-менеджмент
- Кадровый менеджмент
- О бизнесе популярно
- Управление, подбор персонала
- Бизнес
- Менеджмент и кадры
- Продажи
- Экономика
- Ценные бумаги и инвестиции
- Малый бизнес
- Делопроизводство, офис
- Корпоративная культура, бизнес
- Банковское дело
- Финансы
- Зарубежная деловая литература
- Ораторское искусство / риторика
- Личные финансы
- Интернет-бизнес
- Поиск работы
- Государственное и муниципальное управление
- Бухучет и аудит
- Работа с клиентами
- Менеджмент
- Краткое содержание
- Личная эффективность
- Переговоры
- Приключения
- Старинная литература
- Религия и духовность
- Компьютеры и Интернет
- Блог
Читаем без скачивания C++17 STL Стандартная библиотека шаблонов - Яцек Галовиц
Шрифт:
Интервал:
Закладка:
vector<size_t> v (partitions);
for (size_t i {0}; i < samples; ++i) {
++v[rd() / div];
}
5. Теперь у нас есть «аккуратная» гистограмма, содержащая значения-примеры. Чтобы вывести ее на экран, нужно получить более подробную информацию о ее реальных значениях счетчика. Извлечем самое большое значение с помощью алгоритма max_element. Затем разделим это значение на 100. Таким образом можно разделить все значения счетчика на max_div и вывести множество звездочек на консоль, не выходя за значение ширины, равное 100. Если самое крупное значение меньше 100 (это может произойти в случае применения небольшого количества образцов), то воспользуемся max для получения минимального делителя 1:
rand_t max_elm (*max_element(begin(v), end(v)));
rand_t max_div (max(max_elm / 100, rand_t(1)));
6. Теперь выведем гистограмму на консоль. Каждый сегмент получает собственную строку на консоли. Разделив его значение счетчика на max_div и выведя соответствующее количество символов '*', получаем строки гистограммы, которые помещаются в окно консоли:
for (size_t i {0}; i < partitions; ++i) {
cout << setw(2) << i << ": "
<< string(v[i] / max_div, '*') << 'n';
}
}
7. О’кей, на этом все. Теперь перейдем к основной программе. Позволим пользователю определить, сколько сегментов и образцов следует применить:
int main(int argc, char **argv)
{
if (argc != 3) {
cout << "Usage: " << argv[0]
<< " <partitions> <samples>n";
return 1;
}
8. Затем считаем эти переменные из командной строки. Конечно, она содержит строки, которые можно преобразовать в числа с помощью функции std::stoull (stoull — это аббревиатура для string to unsigned long long, строки к беззнаковым значениям типа long long):
size_t partitions {stoull(argv[1])};
size_t samples {stoull(argv[2])};
9. Теперь вызовем нашу вспомогательную функцию, создающую гистограммы, для каждого генератора случайных чисел, предоставляемого STL. Это сделает наш пример длинным и повторяющим код. Лучше скопируйте пример из Интернета. Интересно взглянуть на результат работы данной программы. Начнем с random_device. Это устройство пытается распределить случайность поровну между всеми возможными значениями:
cout << "random_device" << 'n';
histogram<random_device>(partitions, samples);
10. Следующий генератор случайных чисел — это default_random_engine. Тип генератора, на который ссылается данный тип, зависит от конкретной реализации. Он может оказаться одним из следующих генераторов:
cout << "ndefault_random_engine" << 'n';
histogram<default_random_engine>(partitions, samples);
11. Затем опробуем ее для всех других генераторов:
cout << "nminstd_rand0" << 'n';
histogram<minstd_rand0>(partitions, samples);
cout << "nminstd_rand" << 'n';
histogram<minstd_rand>(partitions, samples);
cout << "nmt19937" << 'n';
histogram<mt19937>(partitions, samples);
cout << "nmt19937_64" << 'n';
histogram<mt19937_64>(partitions, samples);
cout << "nranlux24_base" << 'n';
histogram<ranlux24_base>(partitions, samples);
cout << "nranlux48_base" << 'n';
histogram<ranlux48_base>(partitions, samples);
cout << "nranlux24" << 'n';
histogram<ranlux24>(partitions, samples);
cout << "nranlux48" << 'n';
histogram<ranlux48>(partitions, samples);
cout << "nknuth_b" << 'n';
histogram<knuth_b>(partitions, samples);
}
12. Компиляция и запуск программы дадут интересные результаты. Мы увидим длинный список, содержащий выходные данные, и узнаем, что все генераторы случайных чисел имеют разные характеристики. Сначала запустим программу, в которой количество сегментов равно 10, а образцов всего 1000 (рис. 8.5).
13. Затем запустим эту же программу снова. В этот раз количество сегментов все еще будет равно 10, но образцов уже 1,000,000. Станет очевидно, что гистограммы выглядят гораздо лучше, когда мы берем для них больше образцов (рис. 8.6). Это важное наблюдение.
Как это работает
Как правило, перед использованием генератора случайных чисел нужно создать объект этого класса. Полученный объект может быть вызван как функция без параметров, поскольку он перегружает operator(). Тогда каждый вызов будет приводить к получению нового случайного числа. Все очень просто.
В этом разделе мы написали довольно сложную программу, чтобы чуть больше узнать о генераторах случайных чисел. Пожалуйста, поработайте с получившейся программой, запуская ее с разными аргументами командной строки, и проверьте следующее:
□ чем больше образцов мы возьмем, тем больше будут равны наши счетчики разделов;
□ неравенство счетчиков разделов значительно отличается между отдельными генераторами;
□ для большого числа образцов становится понятно, что производительность отдельных генераторов различается;
□ запустите программу с небольшим количеством образцов несколько раз. Шаблоны распределения будут выглядеть одинаково: генераторы постоянно создают одни и те же последовательности; это говорит о том, что они совсем не случайны. Такие генераторы называются детерминированными, поскольку можно предсказать получаемые значения. Единственным исключением является std::random_device.
Как видите, необходимо рассмотреть несколько характеристик. Для большинства стандартных приложений достаточно применить std::default_random_engine. Эксперты в области криптографии или в других областях, чувствительных к безопасности, будут тщательно выбирать один из доступных генераторов, но для нас, типичных программистов, это не так важно.
Из данного примера следует сделать три вывода.
1. Как правило, std::default_random_engine — это хороший вариант по умолчанию для типичного приложения.
2. Если действительно нужно получить недетерминированные случайные числа, то поможет std::random_device.
3. Можно передать конструктору любого генератора случайных чисел реальное случайное число, полученное от std::random_device (или, например, текущее время на системных часах), чтобы заставить его создавать разные случайные числа при каждом обращении. Это называется посевом.
Обратите внимание: std::random_device может откатиться к одному из детерминированных генераторов, если библиотека не поддерживает недетерминированные генераторы.
Генерируем случайные числа и создаем конкретные распределения с помощью STL
Из предыдущего примера мы узнали о генераторах случайных чисел, предоставляемых STL. Генерация случайных чисел тем или иным способом — зачастую лишь половина работы.
Возникает еще один вопрос: для чего нужны эти числа? Мы просто программно «подбрасываем монетку»? Обычно это делается с помощью конструкции rand()%2, что дает результаты 0 и 1, которые можно сопоставить с орлом и решкой. Справедливо; для этого не нужна библиотека (однако эксперты в области случайных чисел знают, что использование лишь нескольких младших битов случайного числа не позволяет получить хорошую подборку случайных чисел).
Что, если мы хотим смоделировать бросок кубика? Конечно, можно написать код (rand()%6)+1 с целью