Está en la página 1de 7

Programación – E.P.

4. Números Aleatorios
Una característica importante en la gran mayoría de lenguajes de programación es la posibilidad de ge-
nerar números aleatorios.

Los números aleatorios son pieza clave en la programación de juegos de azar, simulaciones, cifrado de
datos, en modelos estadísticos, etc. En esta capítulo aprenderemos a generar números aleatorios para
automatizar el proceso de llenado de arreglos y más.

4.1. Generación de números aleatorios enteros


Uno de los métodos más comunes para generar números aleatorios, llamado método congruencial mul-
tiplicativo, comienza con un valor inicial x0 , llamado semilla, y luego se calcula de manera recursiva los
valores sucesivos xn , n ≥ 1, haciendo:

xn = axn−1 mód m

donde a y m son enteros positivos dados y lo anterior significa que axn−1 se divide entre m y el residuo
se considera como el valor de xn .
xn
Así, cada xn toma valores entre: 0, 1, . . . m − 1 y la expresión
(llamada número pseudoaleatorio) se
m
considera como una aproximación del valor de una variable aleatoria uniforme en el intervalo (0, 1).

Figura 1: Números aleatorios

La generación de números aleatorios en C++ se realiza por medio de la función rand(), misma que se
encuentra definida en la librería cstdlib. La función rand() devuelve un número entero aleatorio en el
rango de 0 a RAND_MAX, donde RAND_MAX es el límite superior y este último depende de la capacidad
computacional del ordenador, así como del sistema operativo.
Ejemplo 1. El siguiente programa genera y almacena 20 números enteros aleatorios entre 0 y RAND_MAX.

1 # include <iostream >


2 # include <cstdlib >
3 using namespace std;
4
5 int main (){
6 int vec [20];
7
8 // Generamos valores entre 0 y RAND_MAX

1 Semestre 2021-A
Programación – E.P.N

9 for(int i=0; i <20; i++){


10 vec[i] = rand ();
11 cout << vec[i] << " ";
12 }
13
14 // Limite superior permitido por el equipo
15 cout << "\n El RAND_MAX para este equipo es: " << RAND_MAX ;
16
17 return 0;
18 }

Si ejecutamos varias veces el programa anterior se puede observar que los números obtenidos en cada
ejecución coinciden. Esto se debe principalmente a que la semilla es exactamente la misma en cada
ejecución. Para solventar este problema se recomienda resetear la semilla en cada llamado del código
por medio del siguiente comando:
srand(time(NULL));

donde srand accede al valor de la semilla y time reemplaza el valor de la semilla por la fecha y hora de
ejecución.

Siempre que se desee replicar un experimento o análisis lo recomendado es fijar una semilla. Por ejemplo:
srand(12345)

Ejemplo 2. El siguiente programa genera 5 números aleatorios enteros distintos en cada ejecución.

1 # include <iostream >


2 # include <cstdlib >
3 using namespace std;
4
5 int main (){
6 int vec [5];
7
8 // Semilla aleatoria
9 srand(time(NULL ));
10
11 // Generamos valores entre 0 y RAND_MAX
12 for(int i=0; i <5; i++){
13 vec[i] = rand ();
14 cout << vec[i] << " ";
15 };
16
17 return 0;
18 }

En ocasiones, se hace necesario generar números aleatorios enteros comprendidos en el rango [0, M ],
con M ∈ N. Para ello, definiremos un nuevo límite superior empleado la notación del módulo ( %):

rand() % (Limite superior + 1)


de manera que:
rand() % 5 generará números aleatorios en el rango [0,4]
rand() % 71 generará números aleatorios en el rango [0,70]

2 Semestre 2021-A
Programación – E.P.N

Ejemplo 3. El siguiente programa que genera 100 números aleatorios entre [0, 20] y obtiene la suma de
dichos números.

1 # include <iostream >


2 # include <cstdlib >
3 using namespace std;
4
5 int main (){
6 int vec [100];
7
8 // Semilla aleatoria
9 srand(time(NULL ));
10
11 // Valores aleatorios
12 cout << "Los valores generados son : " << endl;
13 for(int i=0; i <100; i++){
14 vec[i] = rand () % 21;
15 };
16
17 // Calculo suma
18 int suma = 0;
19 for(int i=0; i <100; i++){
20 cout << vec[i] << endl;
21 suma += vec[i];
22 };
23
24 cout << "La suma de los valores generados : " << endl;
25 cout << suma << endl;
26
27 return 0;
28 }

4.2. Generación de números aleatorios decimales


Ahora nos centraremos en la generación de números aleatorios decimales, para ello basta recordar que
xn
el número pseudoaleatorio yn = se distribuye uniformemente en el intervalo (0, 1). Es decir,
m
yn ∼ U [0, 1]

por tanto,
b · yn ∼ U [0, b], para b ∈ R+
y además,
a + b · yn ∼ U [a, a + b], para a ∈ R y b ∈ R+

Ejemplo 4. El siguiente programa genera 10 números aleatorios con 4 decimales en el intervalo [1, 4].

1 # include <iostream >


2 # include <cstdlib >
3 using namespace std;
4
5 int main (){
6 double vec [10];

3 Semestre 2021-A
Programación – E.P.N

7
8 // Semilla aleatoria
9 srand(time(NULL ));
10
11 // Generamos valores entre 0 y RAND_MAX
12 for(int i=0; i <10; i++){
13 vec[i] = 1 + ( double ) (rand () % 30001)/10000;
14 cout << vec[i] << " ";
15 };
16
17 return 0;
18 }

4.3. Evaluación de integrales


Una de las primeras aplicaciones de los números aleatorios fue el cálculo de integrales. Sea g(x) una
función y supongamos que queremos calcular θ, donde:
∫ 1
θ= g(x)dx
0

Para calcular el valor de θ note que si U está distribuida uniformemente en (0, 1), entonces podemos
expresar θ como:
θ = E[g(U )]
Si U1 , U2 , . . . , Uk son variables aleatorias independientes y uniformes en (0, 1), esto implica que g(U1 ), g(U2 ),
. . . , g(Uk ) son variables aleatorias independientes e idénticamente distribuidas con media θ.

Por lo tanto, por la ley fuerte de los grandes números, se tiene, con probabilidad igual a 1 que:


k
g(Ui )
→ E[g(U )] = θ, cuando k → ∞
i=1
k

De lo anterior, podemos aproximar θ generando un gran número de números aleatorios ui y considerando


como nuestra aproximación a θ el valor medio de g(ui ). Este método de aproximación de integrales es
conocido como el método de Monte Carlo.
Ejemplo 5. Aproxime la siguiente integral mediante el método Monte Carlo:
∫ 1
e−x dx
2

Los pasos a seguir para realizar la aproximación son los siguientes:

1. Generar una cantidad suficientemente grande de números aleatorios distribuidos en el rango (0, 1).
2. Evaluar la función que se intenta integrar en cada uno de los números aleatorios anteriores.
3. Obtener el promedio de los resultados obtenidos en el paso 2.

1 # include <iostream >


2 # include <cmath >
3 # include <cstdlib >
4 using namespace std;
5

4 Semestre 2021-A
Programación – E.P.N

6 int main (){


7 int n = 10000; // Cantidad de numeros aleatorios
8 double u, sum =0, prom;
9
10 // Semilla aleatoria
11 srand(time(NULL ));
12
13 // Calculo de la integral
14 for(int i=1; i <=n; i++){
15 u = ( double ) (1 + rand () % 1000)/1000;
16 sum += ( double ) exp(-pow(u ,2));
17 };
18
19 prom = sum/n;
20 // Impresion resultado
21 cout << "Valor integral : " << prom << endl;
22
23 return 0;
24 }

Ejemplo 6. El siguiente programa aproxima la integral:


∫ 1
ex − 1
θ= dx
0 e−1

mediante el método de Monte Carlo.

1 # include <iostream >


2 # include <cmath >
3 # include <cstdlib >
4 using namespace std;
5
6 int main (){
7 int k;
8 double u, sum =0;
9
10 cout << " Ingrese el valor k" << endl;
11 cin >> k;
12
13 // Semilla aleatoria
14 srand(time(NULL ));
15
16 // Calculo de la integral
17 for(int i=0; i<k; i++){
18 u = ( double ) (1 + rand () % 10000)/10000;
19 sum += ( double ) (exp(u) -1)/( exp (1) -1);
20 };
21
22 // Impresion resultado
23 cout << "Valor integral : " << ( double ) sum/k << endl;
24
25 return 0;
26 }

5 Semestre 2021-A
Programación – E.P.N

Si quisiéramos calcular la integral:


∫ b
θ= g(x)dx
a

entonces, al hacer la sustitución:


x−a dx
y= y dy =
b−a b−a
vemos que:
∫ 1
θ= g (a + [b − a]y) (b − a)dy
0
∫ 1
= h(y)dy
0

donde h(y) = (b − a)g (a + [b − a]y). Así, podemos aproximar θ al generar de manera continua números
aleatorios y luego considerar el valor promedio de h evaluada en estos números aleatorios.
Ejemplo 7. El siguiente programa calcula la integral definida:
∫ 5
x
θ= dx
2 x2 − 1

mediante el método de Monte Carlo.

1 # include <iostream >


2 # include <cmath >
3 # include <cstdlib >
4 using namespace std;
5
6 int main (){
7 int k, a=2, b=5;
8 double u, z, sum =0;
9
10 cout << " Ingrese el valor k" << endl;
11 cin >> k;
12
13 // Semilla aleatoria
14 srand(time(NULL ));
15
16 // Calculo integral
17 for(int i=0; i<k; i++){
18 u = ( double ) (1 + rand () % 10000)/10000;
19 z = a + (b-a)*u;
20 sum += (b-a)*(( double ) z/( pow(z ,2) -1));
21 }
22
23 // Impresion resultado
24 cout << "Valor integral : " << ( double ) sum/k << endl;
25
26 return 0;
27 }

De manera análoga, si queremos el valor de


∫ ∞
θ= g(x)dx
0

6 Semestre 2021-A
Programación – E.P.N

podríamos aplicar la sustitución

1 −dx
y= , dy = = −y 2 dx
x+1 (x + 1)2

para obtener la identidad


∫ 1
θ= h(y)dy
0

donde ( )
g 1
y −1
h(y) =
y2

Ejemplo 8. Estudie la convergencia de la integral:


∫ ∞
1
√ dx
0 ex

1 # include <iostream >


2 # include <cmath >
3 # include <cstdlib >
4 using namespace std;
5
6 int main (){
7 int k;
8 double u, z, sum =0;
9
10 cout << " Ingrese el valor k" << endl;
11 cin >> k;
12
13 // Semilla aleatoria
14 srand(time(NULL ));
15
16 // Calculo integral
17 for(int i=0; i<k; i++){
18 u = ( double ) (1 + rand () % 10000)/10000;
19 z = ( float ) 1/u - 1;
20 sum += exp(-z/2)/ pow(u ,2);
21 }
22
23 // Impresion resultado
24 cout << "Valor integral : " << ( double ) sum/k << endl;
25
26 return 0;
27 }

7 Semestre 2021-A

También podría gustarte