Генерация случайных чисел в C++11, Как создать, как они работают? [закрытый]


недавно я столкнулся с новым способом генерации случайных чисел в C++11, но не смог переварить статьи что я читал об этом (что это за движок, математический термин, как распределение, " где все целые числа производятся равной вероятностью").

Так может ли кто-нибудь объяснить, что они такое , что они означают , как генерировать, как они работают? и т. д. (Вы можете назвать все это в одном FAQ о генерации случайных чисел).

2 80

2 ответа:

вопрос слишком широк для полного ответа, но позвольте мне выбрать пару интересных моментов:

почему "с равной вероятностью"

Предположим, у вас есть простой генератор случайных чисел, который генерирует числа 0, 1, ..., 10 каждый с равной вероятностью (думайте об этом как о классическом rand()). Теперь вам нужно случайное число в диапазоне 0, 1, 2, каждое с равной вероятностью. Ваша реакция коленного рефлекса будет принимать rand() % 3. Но подождите, оставшиеся 0 и 1 встречается чаще, чем остальные 2, так что это не правильно!

вот почему нам нужно распределение, которые берут источник однородных случайных целых чисел и превращают их в наше желаемое распределение, например Uniform[0,2] в Примере. Лучше оставить это в хорошей библиотеке!

двигатели

таким образом, в основе всей случайности лежит хороший генератор псевдослучайных чисел, который генерирует последовательность чисел, равномерно распределенных по a определенный интервал, и который в идеале имеют очень длительный период. Стандартная реализация rand() не часто лучших, и поэтому хорошо иметь выбор. Линейно-конгруэнтный и Mersenne twister-это два хороших варианта (LG на самом деле часто используется rand(), тоже); опять же, хорошо, чтобы библиотека справлялась с этим.

как это работает

легко: во-первых, настроить двигатель и посеять его. Семя полностью определяет всю последовательность "случайных" чисел, поэтому а) использовать другой (например, взятый из /dev/urandom) каждый раз, и Б) хранить семена, если вы хотите, чтобы воссоздать последовательность случайных вариантов.

#include <random>

typedef std::mt19937 MyRNG;  // the Mersenne Twister with a popular choice of parameters
uint32_t seed_val;           // populate somehow

MyRNG rng;                   // e.g. keep one global instance (per thread)

void initialize()
{
  rng.seed(seed_val);
}

теперь мы можем создавать дистрибутивы:

std::uniform_int_distribution<uint32_t> uint_dist;         // by default range [0, MAX]
std::uniform_int_distribution<uint32_t> uint_dist10(0,10); // range [0,10]
std::normal_distribution<double> normal_dist(mean, stddeviation);  // N(mean, stddeviation)

...И использовать двигатель для создания случайных чисел!

while (true)
{
  std::cout << uint_dist(rng) << " "
            << uint_dist10(rng) << " "
            << normal_dist(rng) << std::endl;

}

параллелизм

еще одна важная причина предпочесть <random> по сравнению с традиционными rand() Теперь очень ясно и очевидно, как сделать генерацию случайных чисел потокобезопасной: либо предоставьте каждому потоку свой собственный, локальный механизм потока, заполненный на локальном начальном элементе потока, или синхронизируйте доступ к объекту механизма.

- разное

  • Теги интересные статьи на TR1 случайный на codeguru.
  • Википедия имеет хорошее резюме (спасибо, @Justin).
  • в принципе, каждый двигатель должен typedef a result_type, который является правильным целочисленным типом для использования для семени. Я думаю, что у меня был багги реализация один раз, который заставил меня заставить семя для std::mt19937 до uint32_t на x64, в конечном итоге это должно быть исправлено, и вы можете сказать MyRNG::result_type seed_val и таким образом сделать двигатель очень легко заменимы.

генератор случайных чисел-это уравнение, которое, учитывая число, даст вам новое число. Обычно вы либо предоставляете первый номер, либо его вытаскивают из чего-то вроде системного времени.

каждый раз, когда вы просите новый номер, он использует предыдущий номер, чтобы выполнить уравнение.

генератор случайных чисел, не считается очень хорошим, если он имеет тенденцию производить тот же номер чаще, чем другие цифры. т. е. если вы хотите случайное число между один и 5 и у вас такое распределение чисел:

  • 1: 1%
  • 2: 80%
  • 3: 5%
  • 4: 5%
  • 5: 9%

2 генерируется гораздо чаще, чем любое другое число, поэтому он с большей вероятностью будет создан, чем другие числа. Если бы все числа были одинаково похожи, у вас был бы 20% шанс получить каждый номер каждый раз. Говоря по-другому, приведенное выше распределение очень неравномерно, потому что 2 благоприятствует. Один распределение со всеми 20% будет равномерным.

Как правило, если вам нужно истинное случайное число, вы будете извлекать данные из чего-то вроде погоды или другого естественного источника, а не из генератора случайных чисел.