Número aleatorio de C ++ entre 0 y 1

Número aleatorio de C ++ entre 0 y 1
Se genera un número aleatorio dentro de un rango, desde un número mínimo hasta un número máximo. Suponga que estos números mínimos y máximos son mayores que 1. Deje que el número generado dentro del rango sea num. Deje que el número mínimo sea min y deje que el número máximo sea máximo. Con estos, para convertir el número entre 0 y 1, use la fórmula:
random_number = (num - min)/(max - min)

Random_number ahora debe estar entre 0 y 1.
Las siguientes preguntas son cómo generar números aleatorios y cómo decidir Min y Max. De hecho, los números aleatorios, según lo descrito por la especificación C ++ 20, son en realidad números pseudo-aleatorios. La especificación C ++ 20 ofrece una guía para producir números verdaderamente aleatorios (números aleatorios no deterministas). El problema con este generador de números verdaderamente aleatorios es que la responsabilidad del compilador, o el programador, es proporcionar el algoritmo a lo que se considera una generación de números aleatorios no deterministas. Este artículo no aborda números aleatorios no deterministas.

Los números pseudo-aleatorios se generan en una secuencia (un orden) de números, que parecen números aleatorios. La generación de un número aleatorio necesita lo que se llama semilla. La semilla es un valor inicial. Este artículo explica los conceptos básicos de la generación de números aleatorios en C ++ 20. Si el número resultante es mayor que 1, se reduce a entre 0 y 1, utilizando la fórmula anterior. La biblioteca C ++ debe incluirse en el programa para tener una secuencia de números aleatorios o aleatorios.

Contenido del artículo

  • Distribuciones
  • lineal_congruential_engine
  • default_random_engine
  • Clases de distribución de números aleatorios
  • Mejor número aleatorio
  • Conclusión

Distribuciones
Distribución uniforme

Una distribución uniforme es aquella en la que la probabilidad de un número es uno del número total de números en la secuencia. Considere la siguiente secuencia:

0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100

Si estos once números son una secuencia de números aleatorios, cada número ha aparecido una vez de once sucesos. Esto significa que es una distribución uniforme. En la práctica, no todos pueden aparecer una vez. Uno o dos o tres pueden aparecer más de una vez, y no aparecerían en orden regular.

Si el número aleatorio devuelto es 40, entonces el programa debe convertir el número aleatorio entre 0 y 1 usando

random_number = (40 - 0)/(100 - 0)
= 4/10 = 0.4

Aquí, Num es 40; min es 0 y max es 100.

Distribución binomial

La distribución binomial no es una distribución uniforme. "Bi", el prefijo de binomial, significa dos. El número de valores en la distribución binomial está representado por t en c++. Si los números de BI preocupados por la distribución son 2 y 3, y si t es 1, entonces la secuencia es:

2, 3

Si t es 2 para los mismos números de BI (2 y 3), entonces la secuencia se vuelve,

4, 12, 9

Si t es 3 para los mismos números de BI (2 y 3), entonces la secuencia se convierte en,

8, 36, 54, 27

Si t es 4 para los mismos números de BI (2 y 3), entonces la secuencia se convierte en,

16, 96, 216, 216, 81

t es un entero positivo que puede ser más de 4. Para cada valor de t, hay t+1 elementos en la secuencia. Una secuencia depende de los números de BI elegidos y del valor de T. Los números de BI pueden ser cualquier par, e.gramo., 13 y 17. La suma de los números de BI también es importante. Se desarrolla una secuencia a partir de lo que se conoce como el teorema binomial.

Hay otras distribuciones en la biblioteca aleatoria en C++.

lineal_congruential_engine

Hay una serie de motores de números aleatorios en C++. lineal_congruential_engine es uno de ellos. Este motor toma una semilla, la multiplica con un multiplicador y agrega un número C constante al producto para tener el primer número aleatorio. El primer número aleatorio se convierte en la nueva semilla. Esta nueva semilla se multiplica por el mismo 'A', cuyo producto se agrega a la misma C, para tener el segundo número aleatorio. Este segundo número aleatorio se convierte en la nueva semilla para el siguiente número aleatorio. Este procedimiento se repite para tantos números aleatorios como lo requiera el programador.

La semilla aquí tiene el papel de un índice. La semilla predeterminada es 1.

Una sintaxis para el lineal_congruential_engine es:

lineal_congruential_engineLCE

LCE es el nombre de la elección del programador. Esta sintaxis usa la semilla predeterminada de 1. El primer parámetro de plantilla aquí debe especializarse con "un unsigned int". El segundo y el tercero deberían tener los valores reales de 'A' y C. El cuarto debe tener el valor real del número aleatorio máximo esperado, más 1.

Suponiendo que se requiere una semilla del valor 2, entonces la sintaxis sería:

lineal_congruential_engineLCE (2)

Tenga en cuenta la semilla entre paréntesis justo después de LCE.

El siguiente programa ilustra el uso de lineal_congruential_engine, con la semilla predeterminada de 1:

#incluir
#incluir
usando el espacio de nombres STD;
int main ()

lineal_congruential_engineLCE;
cout <cout <cout <cout <cout <cout <cout <cout <regresar 0;

La salida es:

4
13
40
121
364
0
499

Tenga en cuenta la forma en que se instancia el objeto LCE para el motor. Aquí, 'A' es 3, C es 1, y el máximo, esperaba alcanzar el número, M es 500. m es en realidad un módulo - ver más tarde. LCE (), como se usa aquí, no es un constructor. Es un operador que devuelve el siguiente número aleatorio requerido para el motor en la secuencia de salida. El mínimo para este esquema es 0, y Max es 499, y estos se pueden usar para convertir un número devuelto a entre 0 y 1, ver más abajo.

El primer número aleatorio devuelto es 4. Es igual a 1 x 3 + 1 = 4. 4 se convierte en la nueva semilla. El siguiente número aleatorio es 13, que es igual a 4 x 3 + 1 = 13. 13 se convierte en la nueva semilla. El siguiente número aleatorio es 40, que es igual a 13 x 3 + 1 = 40. De esta manera, los números aleatorios siguientes son 121 y 364.

El siguiente código ilustra el uso de lineal_congruential_engine, con una semilla de 2:

lineal_congruential_engineLCE (2);
cout <cout <cout <cout <cout <cout <cout <cout <

La salida es:

7
22
67
202
607
0
999

El número aleatorio máximo que se espera aquí es 1000. El mínimo para este esquema sigue siendo 0, y Max ahora es 999, y estos se pueden usar para convertir un número devuelto a entre 0 y 1 - ver más abajo

El primer número aleatorio devuelto es 7. Es igual a 2 x 3 + 1 = 7. 7 se convierte en la nueva semilla. El siguiente número aleatorio es 22, que es igual a 7 x 3 + 1 = 22. 22 se convierte en la nueva semilla. El siguiente número aleatorio es 67, que es igual a 22 x 3 + 1 = 67. De esta manera, los números aleatorios siguientes son 202 y 607.

El siguiente código utiliza la fórmula anterior para producir un número aleatorio entre 0 y 1, para este motor:

lineal_congruential_engineLCE (2);
unsigned int num = lce (); // Número aleatorio normal
Unsigned int min = lCE.min ();
unsigned int max = lCE.max ();
float random_number = ((float) (num - min))/((float) (max - min));
cout <

La salida es:

0.00700701

Aquí, Num es 7, y así

random_number = (7 - 0)/(999 - 0) = 7/999 = 0.00700701 redondeado a 8 decimales.

lineal_congruential_engine no es el único motor especializado en la biblioteca aleatoria; hay otros.

default_random_engine

Esto es como un motor de uso general. Produce números aleatorios. No se garantiza que el orden de secuencia no esté determinado. Sin embargo, el programador probablemente no conoce el pedido. Las siguientes dos líneas muestran cómo se puede usar este motor:

random_device rd;
default_random_engine Eng (rd ());

random_device es una clase de la que RD ha sido instanciado. Tenga en cuenta los paréntesis de RD en las listas de argumentos del motor. Un distribuidor necesita este motor para su operación; consulte a continuación.

Clases de distribución de números aleatorios
uniforme_int_distribución

uniforme_int_distribución
La probabilidad de que ocurra cualquier número se divida por el número total de números para esta clase. Por ejemplo, si hay diez posibles números de salida, la probabilidad de que se muestre cada número es 1/10. El siguiente código ilustra esto:

random_device rd;
default_random_engine Eng (rd ());
uniforme_int_distribucióndist (3, 12);
cout <cout <

La salida de la computadora del autor es:

9 8 3 5 12
7 4 11 7 6

Desafortunadamente, 7 ha aparecido dos veces a expensas de 10. Los argumentos de DIST son los números 3 y 13 inclusive (diez enteros consecutivos). DIST (ENG) es un operador que devuelve el siguiente número. Utiliza el motor. Tenga en cuenta el uso de la especialización de plantilla de int.

No es necesario buscar NUM, MIN y Max para este caso y luego usar la fórmula anterior para obtener un número entre 0 y 1. Esto se debe a que hay un equivalente flotante de esta clase que utiliza la especialización de flotación. La salida no será la misma para cada ejecución.

uniforme_real_distribución

uniforme_real_distribution es similar a uniforme_int_distribution. Con él, para obtener un número entre 0 y 1, simplemente use 0 y 1 como argumentos. El siguiente código ilustra esto:

random_device rd;
default_random_engine Eng (rd ());
uniforme_real_distribucióndist (0, 1);
cout <cout <

La salida de la computadora del autor es:

0.384051 0.745187 0.364855 0.122008 0.580874
0.745765 0.0737481 0.48356 0.184848 0.745821

Tenga en cuenta el uso de la especialización de plantilla de flotación. La salida no será la misma para cada ejecución.

Distribución binomial

Con esta distribución, la probabilidad de cada número de salida no es la misma. binomial_distribution se ha ilustrado arriba. El siguiente código muestra cómo usar el binomial_distribution para producir 10 números aleatorios:

random_device rd;
default_random_engine Eng (rd ());
Distribución binomialdist (10);
cout <cout <

La salida de la computadora del autor es:

5 3 5 5 7
6 6 5 8 3

La salida no será la misma para cada ejecución. La especialización de plantilla utilizada aquí es int.

El siguiente código utiliza la fórmula anterior para producir un número aleatorio entre 0 y 1, para esta distribución:

random_device rd;
default_random_engine Eng (rd ());
Distribución binomialdist (10);
Unsigned int num = Dist (Eng); // Número aleatorio normal
Unsigned int min = dist.min ();
unsigned int max = Dist.max ();
cout <cout <cout <cout <float random_number = ((float) (num - min))/((float) (max - min));
cout <

La salida de la computadora del autor es:

0
10
7
0.7

Mejor número aleatorio

El número de segundos desde que la época unix se puede usar como semilla. Se hace difícil para el hacker conocer la semilla. El siguiente programa ilustra esto con Linear_Congruential_Engine:

#incluir
#incluir
#incluir
usando el espacio de nombres STD;
int main ()

const auto p1 = crono :: system_clock :: ahora ();
unsigned int sement = Chrono :: Duration_cast(P1.Time_since_epoch ()).contar();
lineal_congruential_enginelCE (semilla);
cout <cout <cout <cout <regresar 0;

La salida de la computadora del autor es:

91 274 823 470 411
0
999

Tenga en cuenta que la biblioteca de Chrono ha sido incluida. La salida es diferente para cada ejecución.

Conclusión

La forma más fácil de tener un número aleatorio entre 0 y 1 es usar el random_device, el default_random_engine y el uniform_real_distribution (con los argumentos 0 y 1). Cualquier otro motor o distribución utilizada puede necesitar la fórmula, Random_Number = (num - min)/(máx - min).