Недавно я наткнулся на новый способ генерации случайных чисел в C ++ 11, но не смог переварить статьи, которые я читал об этом (что это за движок , такой математический термин, как распределение , «где все полученные целые числа одинаково вероятны »).
Так может кто-нибудь объяснить
- кто они такие?
- что они означают?
- как сгенерировать?
- как они работают?
- и т.д
Вы можете назвать все это в одном FAQ о генерации случайных чисел.
rand
, вам следует быстро взглянуть на Википедию, чтобы узнать о некоторых основных понятиях статистики и ГСЧ, иначе будет очень сложно объяснить вам смысл<random>
и использование различных его частей.Ответы:
Вопрос слишком широкий для полного ответа, но позвольте мне выделить пару интересных моментов:
Почему "одинаково вероятно"
Предположим, у вас есть простой генератор случайных чисел, который генерирует числа 0, 1, ..., 10 каждое с равной вероятностью (считайте это классическим
rand()
). Теперь вам нужно случайное число в диапазоне 0, 1, 2, каждое с равной вероятностью. Ваша реакция коленного рефлекса - принятьrand() % 3
. Но подождите, остатки 0 и 1 встречаются чаще, чем остаток 2, так что это неверно!Вот почему нам нужны правильные распределения , которые берут источник однородных случайных целых чисел и превращают их в желаемое распределение, как
Uniform[0,2]
в примере. Лучше оставить это хорошей библиотеке!Двигатели
Таким образом, в основе всей случайности лежит хороший генератор псевдослучайных чисел, который генерирует последовательность чисел, равномерно распределенных в определенном интервале и в идеале имеющих очень длинный период. Стандартная реализация
rand()
часто не самая лучшая, и поэтому хорошо иметь выбор. Линейно-конгруэнтный и твистер Мерсенна - два хороших выбора (LG на самом деле часто используетсяrand()
тоже ); опять же, хорошо позволить библиотеке справиться с этим.Как это устроено
Легко: сначала установите двигатель и засевайте его. Начальное число полностью определяет всю последовательность «случайных» чисел, поэтому: а) используйте
/dev/urandom
каждый раз другое (например, взятое из ), и б) сохраните начальное число, если вы хотите воссоздать последовательность случайных выборов.Теперь мы можем создавать раздачи:
... И используйте движок для создания случайных чисел!
Параллелизм
Еще одна важная причина, по которой следует предпочесть
<random>
традиционное,rand()
заключается в том, что теперь очень ясно и очевидно, как сделать генерацию случайных чисел потокобезопасной: либо предоставить каждому потоку свой собственный, локальный для потока движок, засеянный на локальном потоке, либо синхронизировать доступ к объекту двигателя.Разное
result_type
, который является правильным интегральным типом для использования в качестве начального числа. Я думаю , что у меня был глючная реализация однажды что заставило меня заставить семя ,std::mt19937
чтобыuint32_t
на x64, в конце концов , это должно быть исправлено , и вы можете сказать ,MyRNG::result_type seed_val
и , таким образом , сделать двигатель очень легко заменить.источник
std::random_device
, стоит упомянуть, а не/dev/urandom
std::random_device
можно найти здесь .Генератор случайных чисел - это уравнение, которое при заданном числе даст вам новое число. Обычно вы либо указываете первое число, либо извлекаете его из системного времени.
Каждый раз, когда вы запрашиваете новый номер, он использует предыдущий номер для выполнения уравнения.
Генератор случайных чисел не считается очень хорошим, если он имеет тенденцию генерировать одно и то же число чаще, чем другие числа. то есть, если вам нужно случайное число от 1 до 5, и у вас было такое распределение чисел:
2 генерируется FAR чаще, чем любое другое число, поэтому вероятность его создания выше, чем других чисел. Если бы все числа были одинаковыми, у вас был бы 20% шанс каждый раз получать каждое число. Другими словами, приведенное выше распределение очень неравномерно, потому что 2 является предпочтительным. Распределение со всеми 20% было бы даже.
Как правило, если вам нужно истинное случайное число, вы извлекаете данные из чего-то вроде погоды или другого естественного источника, а не из генератора случайных чисел.
источник