C++
Generación de números aleatorios
Buscar..
Observaciones
La generación de números aleatorios en C ++ es proporcionada por el encabezado <random>
. Este encabezado define dispositivos aleatorios, generadores pseudoaleatorios y distribuciones.
Los dispositivos aleatorios devuelven números aleatorios proporcionados por el sistema operativo. Deben utilizarse para la inicialización de generadores pseudoaleatorios o directamente con fines criptográficos.
Los generadores seudoaleatorios devuelven números enteros pseudoaleatorios basados en su semilla inicial. El rango de números pseudoaleatorios generalmente abarca todos los valores de un tipo sin signo. Todos los generadores seudoaleatorios en la biblioteca estándar devolverán los mismos números para la misma semilla inicial para todas las plataformas.
Las distribuciones consumen números aleatorios de generadores seudoaleatorios o dispositivos aleatorios y producen números aleatorios con la distribución necesaria. Las distribuciones no son independientes de la plataforma y pueden producir diferentes números para los mismos generadores con las mismas semillas iniciales en diferentes plataformas.
Generador de valor aleatorio verdadero
Para generar valores aleatorios verdaderos que se pueden usar para la criptografía std::random_device
se debe usar como generador.
#include <iostream>
#include <random>
int main()
{
std::random_device crypto_random_generator;
std::uniform_int_distribution<int> int_distribution(0,9);
int actual_distribution[10] = {0,0,0,0,0,0,0,0,0,0};
for(int i = 0; i < 10000; i++) {
int result = int_distribution(crypto_random_generator);
actual_distribution[result]++;
}
for(int i = 0; i < 10; i++) {
std::cout << actual_distribution[i] << " ";
}
return 0;
}
std::random_device
se usa de la misma manera que se usa un generador de valores pseudoaleatorios.
Sin embargo, std::random_device
puede implementarse en términos de un motor de números pseudoaleatorios definido por la implementación si una fuente no determinista (por ejemplo, un dispositivo de hardware) no está disponible para la implementación.
Detectar dichas implementaciones debería ser posible a través de la función de miembro de entropy
(que devuelve cero cuando el generador es completamente determinista), pero muchas bibliotecas populares (tanto libstdc ++ de GCC como libc ++ de LLVM) siempre devuelven cero, incluso cuando utilizan aleatoriedad externa de alta calidad .
Generando un número pseudoaleatorio
Un generador de números pseudoaleatorios genera valores que se pueden calcular basándose en valores generados previamente. En otras palabras: es determinista. No utilice un generador de números pseudoaleatorios en situaciones donde se requiera un número aleatorio verdadero.
#include <iostream>
#include <random>
int main()
{
std::default_random_engine pseudo_random_generator;
std::uniform_int_distribution<int> int_distribution(0, 9);
int actual_distribution[10] = {0,0,0,0,0,0,0,0,0,0};
for(int i = 0; i < 10000; i++) {
int result = int_distribution(pseudo_random_generator);
actual_distribution[result]++;
}
for(int i = 0; i <= 9; i++) {
std::cout << actual_distribution[i] << " ";
}
return 0;
}
Este código crea un generador de números aleatorios y una distribución que genera números enteros en el rango [0,9] con la misma probabilidad. Luego cuenta cuántas veces se generó cada resultado.
El parámetro de plantilla de std::uniform_int_distribution<T>
especifica el tipo de entero que se debe generar. Use std::uniform_real_distribution<T>
para generar flotantes o dobles.
Uso del generador para múltiples distribuciones.
El generador de números aleatorios puede (y debe) ser usado para múltiples distribuciones.
#include <iostream>
#include <random>
int main()
{
std::default_random_engine pseudo_random_generator;
std::uniform_int_distribution<int> int_distribution(0, 9);
std::uniform_real_distribution<float> float_distribution(0.0, 1.0);
std::discrete_distribution<int> rigged_dice({1,1,1,1,1,100});
std::cout << int_distribution(pseudo_random_generator) << std::endl;
std::cout << float_distribution(pseudo_random_generator) << std::endl;
std::cout << (rigged_dice(pseudo_random_generator) + 1) << std::endl;
return 0;
}
En este ejemplo, solo se define un generador. Posteriormente se utiliza para generar un valor aleatorio en tres distribuciones diferentes. La distribución rigged_dice
generará un valor entre 0 y 5, pero casi siempre genera un 5
, porque la posibilidad de generar un 5
es 100 / 105
.