std::mt19937 Класс в C++
Класс std::mt19937 (начиная с C++11) является очень эффективным генератором псевдослучайных чисел и определяется в случайном заголовочном файле. Он производит 32-битные псевдослучайные числа, используя хорошо известный и популярный алгоритм, называемый алгоритмом скручивания Мерсенна. Класс std::mt19937 в основном является типом класса std::mersenne_twister_engine.
typedef mersenne_twister_engine<uint_fast32_t, 32,624,397,31,0x9908b0df,11,0xffffffff,7,0x9d2c5680,15,0xefc60000,18,1812433253> mt19937;
Синтаксис:
mt19937 mt1(seed_value);
Здесь mt1 является экземпляром класса mt19937, и для создания всей последовательности требуется начальное значение.
Значение имени mt19937
mt19937 означает скручивание Мерсенна с длинным периодом 2 19937 – 1, что означает, что mt19937 создает последовательность 32-битных целых чисел, которая повторяется только после того, как 2 19937 – 1 число было сгенерировано.
Сходства между mt19937 и rand() и srand():
std::mt19937 делает две вещи:
- Когда создается экземпляр объекта std::mt19937, он принимает аргумент, который используется для генерации начального значения (например, srand()).
- Используя оператор(), он генерирует случайное число (например, rand()).
Ниже приведен пример, демонстрирующий сходство:
Будучи типом класса std::mersenne_twister_engine, он имеет те же функции-члены, что и mersenne_twister_engine. Вот список некоторых важных функций-членов:
1. (конструктор): создает объект mt19937. Он принимает либо начальное значение типа результата, либо объект начальной последовательности (аналогично функции srand()).
Пример :
2. min(): возвращает минимальное значение, которое может вернуть оператор() (равное нулю).
Пример:
3. max(): возвращает максимальное значение, которое может вернуть оператор() (то есть 2 32 – 1 = 4294967295)
Пример :
4. seed(): повторно инициализирует начальное значение объекта, либо беря начальное значение типа результата, либо беря начальный объект последовательности.
Пример :
5. operator(): генерирует псевдослучайные целые числа (аналогично функции rand()).
Пример:
Существуют также функции, не являющиеся членами, перегруженные для работы с объектом std::mt19937. Это -
- operator<<() — перегружен, чтобы мы могли напрямую печатать значение, сгенерированное объектом mt19937, в выходной поток.
- operator>>() — используется для извлечения начального значения из ввода.
Вот простой пример генерации псевдослучайного числа путем получения начального значения от пользователя:
Используя оператор<<() и оператор>>() :
Пример :
Зачем использовать mt19937 вместо rand()?
Хотя функцию rand() можно использовать в небольшом диапазоне, она неэффективна для генерации реальных случайных чисел. Внимательный человек может заметить повторение случайных чисел, сгенерированных функцией rand(), что очень рискованно. Принимая во внимание, что std::mt19937 имеет следующие преимущества:
- У него очень длинный период по сравнению с rand(). Это займет больше времени. Если бы реализация вихря Мерсенна могла генерировать 1 000 000 000 (один миллиард) псевдослучайных чисел каждую секунду, программе, генерирующей псевдослучайные числа, потребовалось бы примерно 1,3684 × 105 985 лет для повторения случайной последовательности. Поэтому можно с уверенностью предположить, что наблюдатель никогда не угадает число.
- Многие генераторы случайных чисел могут быть запущены одновременно с разными начальными значениями. Вот пример —