Как следует из названия, я пытаюсь найти способ генерирования случайных чисел с помощью новой <random>
библиотеки C ++ 11 . Я пробовал это с этим кодом:
std::default_random_engine generator;
std::uniform_real_distribution<double> uniform_distance(1, 10.001);
Проблема с кодом, который у меня есть, заключается в том, что каждый раз, когда я компилирую и запускаю его, он всегда генерирует одинаковые числа. Итак, мой вопрос: какие другие функции в случайной библиотеке могут выполнить это, будучи действительно случайным?
Для моего конкретного случая использования я пытался получить значение в диапазоне [1, 10]
std::mt19937
качестве двигателя, если у вас нет веских причин не делать этого. И распределение это закрытый интервал с обоих концов.std::uniform_int_distribution
, который будет закрыт на обоих концах.Ответы:
Стефан Т. Лававей (stl) из Microsoft выступил в Going Native с докладом о том, как использовать новые случайные функции C ++ 11 и почему их не использовать
rand()
. В него он включил слайд, который в основном решает ваш вопрос. Я скопировал код из этого слайда ниже.Вы можете увидеть его полный доклад здесь: http://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful
Мы используем
random_device
один раз для заполнения генератора случайных чисел по имениmt
.random_device()
медленнее, чемmt19937
, но его не нужно заполнять, потому что он запрашивает случайные данные из вашей операционной системы (которая будет получать источники из разных мест, например, RdRand ).Глядя на этот вопрос / ответ , кажется, что
uniform_real_distribution
возвращает число в диапазоне[a, b)
, где вы хотите[a, b]
. Чтобы сделать это, нашuniform_real_distibution
должен выглядеть так:источник
default_random_engine
, согласноdefault_random_engine
существует.std::default_container
, надеюсь, что нет Люди, считающие себя программистами, которые не знают различий, многие языки сценариев имеют структуру типов карт по умолчанию, которая может быть реализована различными способами, которые пользователь может не знатьnextafter
Вызов является излишеством для большинства приложений. Шансы на случайнуюdouble
посадку точно в конечной точке настолько малы, что нет практической разницы между включением и исключением.std::vector
аналогия здесь не работает, потому чтоstd::vector
на самом деле является хорошим значением по умолчанию из-за кэширования процессора. Это даже превосходитstd::list
для вставки в середине. Это верно, даже если вы понимаете все контейнеры и можете принять обоснованное решение на основе алгоритмической сложности.Моя «случайная» библиотека обеспечивает удобную оболочку вокруг случайных классов C ++ 11. Вы можете сделать почти все с помощью простого метода get.
Примеры:
Случайное число в диапазоне
Случайный логический
Случайное значение из списка std :: initilizer_list
Случайный итератор из диапазона итератора или всего контейнера
И даже больше вещей! Проверьте страницу GitHub:
https://github.com/effolkronium/random
источник
Я переделал все вышеперечисленное, около 40 других страниц с c ++ в нем, вот так, и посмотрел видео от Stephan T. Lavavej «STL», и все еще не был уверен, как случайные числа работают в практике, поэтому я взял целое воскресенье, чтобы выяснить, что это такое и как оно работает и может быть использовано.
По моему мнению, STL прав насчет «не использовать srand больше», и он хорошо объяснил это в видео 2 . Он также рекомендует использовать:
а)
void random_device_uniform()
- для зашифрованной генерации, но медленнее (из моего примера)б) примеры с
mt19937
- быстрее, возможность создавать семена, не зашифрованыЯ вытащил все заявленные книги на c ++ 11, к которым у меня есть доступ, и обнаружил, что немецкие авторы, такие как Breymann (2015), до сих пор используют клон
просто
<random>
вместо<time> and <cstdlib>
#includes - так что будьте осторожны, изучая только одну книгу :).Значение - это не должно использоваться с c ++ 11, потому что:
В конце концов, я нашел лучшее объяснение из 20 книг Бьярна Страуструпса, более новых - и он должен знать свои вещи - в «Путешествии по C ++ 2019», «Принципы и практика программирования с использованием C ++ 2016» и «Язык программирования C ++, 4-е издание». 2014 », а также некоторые примеры из« Учебника по Липпману C ++, пятое издание 2012 »:
И это действительно просто, потому что генератор случайных чисел состоит из двух частей: (1) механизм, который генерирует последовательность случайных или псевдослучайных значений. (2) распределение, которое отображает эти значения в математическое распределение в диапазоне.
Несмотря на мнение парня из Microsoft STL, Бьярн Страуструпс пишет:
void die_roll()
Пример от Бьярна Stroustrups - хорошая идея генерации двигатель и распределение сusing
(более боем , что здесь) .Чтобы иметь возможность на практике использовать генераторы случайных чисел, предоставляемые стандартной библиотекой, приведем
<random>
здесь некоторый исполняемый код с различными примерами, сведенными к минимуму необходимости, который, как мы надеемся, сэкономит вам время и деньги:Я думаю, что все это складывается, и, как я уже сказал, мне потребовалось много времени для чтения и времени, чтобы перенести это на эти примеры - если у вас есть дополнительные сведения о генерации чисел, я буду рад услышать об этом в личку или в разделе комментариев. и добавит его при необходимости или отредактирует этот пост. Bool
источник
Вот то, что я только что написал в том же духе:
~
источник
Вот некоторый ресурс, который вы можете прочитать о генераторе псевдослучайных чисел.
https://en.wikipedia.org/wiki/Pseudorandom_number_generator
В основном, случайные числа в компьютере требуют начального числа (это число может быть текущим системным временем).
замещать
По
источник
У вас есть две общие ситуации. Во-первых, вам нужны случайные числа, и вы не слишком беспокоитесь о качестве или скорости выполнения. В этом случае используйте следующий макрос
это дает вам p в диапазоне от 0 до 1 - эпсилон (если только RAND_MAX не превосходит точность двойного, но не беспокойтесь об этом, когда придете к нему).
int x = (int) (iform () * N);
Теперь дает случайное целое число от 0 до N -1.
Если вам нужны другие дистрибутивы, вы должны трансформировать p. Или иногда проще вызыватьiform () несколько раз.
Если вы хотите повторить поведение, начните с константы, в противном случае начните с вызова time ().
Теперь, если вы беспокоитесь о качестве или производительности во время выполнения, перепишите формуiform (). Но в противном случае не трогайте код. Всегда держите форму () от 0 до 1 минус эпсилон. Теперь вы можете обернуть библиотеку случайных чисел в C ++, чтобы создать более удобную форму (), но это своего рода опция среднего уровня. Если вас беспокоят характеристики ГСЧ, то также стоит потратить немного времени, чтобы понять, как работают базовые методы, а затем представить один из них. Таким образом, у вас есть полный контроль над кодом, и вы можете гарантировать, что с одним и тем же начальным числом последовательность всегда будет одинаковой, независимо от платформы или версии C ++, на которую вы ссылаетесь.
источник