La clase std::mt19937 (desde C++11) es un generador de números pseudoaleatorios muy eficiente y se define en un archivo de encabezado aleatorio. Produce números pseudoaleatorios de 32 bits utilizando el conocido y popular algoritmo denominado Mersenne twister. La clase std::mt19937 es básicamente un tipo de clase 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;
Sintaxis:
mt19937 mt1(seed_value);
Aquí mt1 es una instancia de la clase mt19937 y se necesita un valor inicial para generar una secuencia completa.
Importancia del nombre mt19937
mt19937 significa mersenne twister con un período largo de 2 19937 – 1, lo que significa que mt19937 produce una secuencia de enteros de 32 bits que solo se repite después de que se haya generado 2 19937 – 1 número.
Similitudes entre mt19937 y rand() y srand():
El std::mt19937 hace dos cosas:
- Cuando se crea una instancia de un objeto std::mt19937, toma un argumento que se usa para generar un valor semilla (como srand()).
- Al usar operator(), genera un número aleatorio (como rand()).
A continuación se muestra el ejemplo para demostrar las similitudes:
C++
// C++ program for demonstrating // similaritites #include <ctime> #include <iostream> #include <random> using namespace std; int main() { // Initializing the sequence // with a seed value // similar to srand() mt19937 mt(time(nullptr)); // Printing a random number // similar to rand() cout << mt() << '\n'; return 0; }
3529725061
Al ser un tipo de clase std::mersenne_twister_engine, tiene las mismas funciones de miembro que hace mersenne_twister_engine. Aquí está la lista de algunas funciones importantes de los miembros:
1. (constructor): construye el objeto mt19937. Toma un valor inicial del tipo de resultado o un objeto de secuencia inicial (similar a la función srand()).
Ejemplo :
C++
// C++ program to implement // the above concept // This header file is // for time #include <ctime> #include <iostream> #include <random> using namespace std; int main() { // Using the constructor to // initialize with a seed value mt19937 mt(time(nullptr)); // Operator() is used to // generate random numbers cout << mt() << '\n'; return 0; }
3529725061
2. min(): devuelve el valor mínimo que puede devolver operator() (que es cero).
Ejemplo:
C++
// C++ program for the // min() #include <ctime> #include <iostream> #include <random> using namespace std; // Driver code int main() { // Initializing mt19937 // object mt19937 mt(time(nullptr)); // Prints the minimum value // which is 0 cout << "the minimum integer it can generate is " << mt.min() << endl; return 0; }
the minimum integer it can generate is 0
3. max(): devuelve el valor máximo que puede devolver operator() (que es 2 32 – 1 = 4294967295)
Ejemplo :
C++
// C++ program to demonstrate // max() #include <ctime> #include <iostream> #include <random> using namespace std; // Driver code int main() { // Initializing mt19937 // object mt19937 mt(time(nullptr)); // Prints the maximum value // which is 4294967295 cout << "mt19937 can generate random numbers upto " << mt.max() << endl; return 0; }
mt19937 can generate random numbers upto 4294967295
4. seed(): reinicializa el valor inicial del objeto tomando un valor inicial del tipo de resultado o tomando un objeto de secuencia inicial.
Ejemplo :
C++
// C++ program to demonstrate // seed() #include <iostream> #include <random> using namespace std; // Driver code int main() { // Defining the // mt19937 object mt19937 mt; // Initializing a random // sequence with a seed value mt.seed(45218965); cout << "some random numbers generated by mt19937 are:" << endl; for (int i = 5; i > 0; i--) { cout << mt() << ' '; } return 0; }
some random numbers generated by mt19937 are: 3334444225 240363925 3350157104 146869560 639267854
5. operator(): genera enteros pseudoaleatorios (similar a la función rand()).
Ejemplo:
C++
// C++ program to demonstrate // operator() #include <ctime> #include <iostream> #include <random> using namespace std; // Driver code int main() { // Initializing mt19937 // object mt19937 mt(time(nullptr)); for (int i = 0; i < 5; i++) { // operator() is used to // generate random numbers cout << mt() << ' '; } return 0; }
3529725061 3019704141 2006641117 725527349 3631905871
También hay funciones que no son miembros sobrecargadas para trabajar con el objeto std::mt19937. Estos son –
- operator<<() : está sobrecargado para que podamos imprimir directamente el valor generado por el objeto mt19937 en el flujo de salida.
- operator>>() : se utiliza para extraer el valor inicial de la entrada.
Aquí hay un ejemplo simple para generar un número pseudoaleatorio tomando un valor inicial del usuario:
Usando operator<<() y operator>>() :
Ejemplo :
C++
// C++ program to demonstrate // operator>>() and <<operator() #include <ctime> #include <iostream> #include <random> using namespace std; // Driver code int main() { mt19937 mt; cout << "enter a integer to begin" << endl; // operator>>() is used to get // a seed value from the user cin >> mt; // <<operator() is used to print // the random integer cout << "a random number " << mt() << " is generated"; return 0; }
enter a integer to begin a random number 3499211612 is generated
¿Por qué usar mt19937 en lugar de rand()?
Aunque la función rand() se puede usar en un rango pequeño, es ineficiente para generar números aleatorios del mundo real. Una persona cuidadosa puede observar las repeticiones de los números aleatorios generados por rand(), lo cual es muy arriesgado. Mientras que std::mt19937 tiene las siguientes ventajas:
- Tiene un período muy largo en comparación con el rand(). Tomará más tiempo. Si una implementación del tornado de Mersenne pudiera generar 1 000 000 000 (mil millones) de números pseudoaleatorios por segundo, un programa que generara números pseudoaleatorios necesitaría ejecutarse aproximadamente 1,3684 × 105 985 años para repetir la secuencia aleatoria. Por lo tanto, es seguro asumir que un observador nunca adivinará el número.
- Muchos generadores de números aleatorios pueden iniciarse simultáneamente con diferentes valores semilla. Aquí hay un ejemplo –
C++
// C++ program to demonstrate // above approach #include <iostream> #include <random> using namespace std; // Driver code int main() { mt19937 mt1(10000); mt19937 mt2(100000); cout << mt1() << endl; cout << mt2() << endl; return 0; }
2342776460 1235064505