Generar valores aleatorios tirando dados en C++

Jay Shaw 12 octubre 2023
  1. Genera números aleatorios tirando dados en C++
  2. Genere valores aleatorios similares a una tirada de dados usando C++
  3. Conclusión
Generar valores aleatorios tirando dados en C++

Las computadoras no pueden adivinar números. Cada vez que una máquina genera un número aleatorio, es producto de alguna operación bit a bit o un derivado de un factor numérico, es decir, tiempo, secuencias.

El problema con el uso de los métodos anteriores es que producirán el mismo conjunto de resultados si se repiten suficientes veces.

Esta es la razón por la que los algoritmos convencionales utilizados para generar números aleatorios no se recomiendan para las prácticas criptográficas. Los resultados son fáciles de predecir.

Al predecir la aleatoriedad, tirar los dados es una tarea bastante sencilla. En este artículo, el lector aprenderá sobre la aleatoriedad en las computadoras y cómo se pueden obtener resultados aleatorios de una simple tirada de dados usando C++.

Genera números aleatorios tirando dados en C++

Un generador pseudoaleatorio es una máquina que crea números que parecen aleatorios. Por el contrario, son totalmente predecibles.

Esto se debe a que los generadores de números aleatorios tradicionales emplean el uso de una semilla. Una semilla, en términos simples, es una función inyectiva que depende de un tiempo o un componente numérico.

Por ejemplo, los resultados producidos para una semilla dada x(0) al aplicar repetidamente una función inyectiva sobre x(0), denominada f(x0), de modo que fn(x0) difiere de fn-1(x0) o fn+1(x0), donde fn representa la estructura de la función n veces.

En otras palabras, f(x) contiene grandes saltos que prácticamente no tienen relación con los anteriores.

Semilla usando el tiempo para crear un número aleatorio para la tirada de dados en C++

En la mayoría de los casos, las semillas generadas dependen del factor tiempo. Eso significa que la función inyectiva factoriza el segundo actual en el reloj.

Veamos un ejemplo para entenderlo mejor.

unsigned main_seed;

main_seed = time(0);

srand(main_seed);

Aquí, se inicializa una variable sin firmar main_seed; esta variable se utiliza para almacenar la hora actual. srand() es una función de C++ que genera un resultado a partir de la semilla.

Una vez que se genera la semilla, la función rand() se puede usar como semilla para generar valores aleatorios usando una ecuación lineal.

El uso del factor tiempo para obtener semillas distintivas puede parecer una buena práctica, a menos que las CPU modernas estén involucradas porque se ocupan de los procesos en nanosegundos, lo que interrumpe toda la función en términos de aleatoriedad.

En la mayoría de los casos, las semillas generadas dependen del factor tiempo. Eso significa que la función inyectiva factoriza el segundo actual en el reloj.

Debido a que el reloj no es tan rápido como se podría pensar, si se usa srand(tiempo) varias veces en un segundo, se obtiene la misma semilla varias veces. Como consecuencia, el conjunto producido de números aleatorios será similar.

Y esto podría ser un problema (significativo), especialmente en los programas de cifrado de bloques. En el último caso, la gente compra una cantidad decente de generadores basados ​​en adjetivos físicos en tiempo real, como la variación de temperatura en los datos atmosféricos, etc., o, últimamente, en la medición de bits cuánticos, por ejemplo, en el factor de cómo se superponen los fotones polarizados.

Semilla usando números arbitrarios para crear números aleatorios para tirada de dados en C++

El siguiente ejemplo muestra un generador de pseudo números usando números.

static unsigned long int rand_num = 2;

int rand(void)  // The ceiling limit is kept at 32767
{
  rand_num = rand_num * 113546545 + 12345;
  return (unsigned int)(rand_num / 65536) % 32768;
}

void srand(unsigned int main_seed)  // seed is stored inside variable main_seed
{
  rand_num = main_seed;
}

Una variable int sin signo rand_num se inicializa con el valor 2. Hay dos métodos en el programa anterior: rand y srand.

El método rand concatena un nuevo número al valor inicializado. A medida que se establece el límite máximo para la semilla, la modificación de rand y el límite máximo devolverán un número inferior al límite máximo.

El resultado final devuelto por este método se encasilla en un int sin firmar.

El método srand() pasa el valor de rand_num a la variable semilla main_seed.

Inconvenientes de usar los métodos anteriores

Como puede verse, ejecutar srand(time(0)) o tomar valores arbitrarios para semilla siempre devuelve números nuevos en rand(), que dependen de la semilla. Pero después de unos pocos millones, los números se repiten.

La semilla controla qué números aleatorios se crean en orden, es decir, srand(1) casi siempre producirá el mismo valor en la primera llamada a rand(), el mismo número en la segunda llamada a rand() , y así.

En otras palabras, la salida es siempre el mismo número aleatorio si la misma semilla se vuelve a sembrar antes de cada llamada rand(). Por lo tanto, sembrar varias veces con tiempo (0) en un solo segundo dará como resultado que todos los números aleatorios sean los mismos después de volver a sembrar.

Debe repetirse después de algunos ciclos, pero el argumento srand define el patrón. C++ rand no es adecuado para el cifrado, ya que conocer la semilla ayuda a un pirata informático a estimar el siguiente número.

Genere valores aleatorios similares a una tirada de dados usando C++

Este programa utiliza una semilla generada por el tiempo para producir números aleatorios en el rango de 1 a 6.

Importar paquetes

Se necesitan tres paquetes de importación en este programa:

  1. iostream
  2. cstdlib - para funciones de tiempo y operaciones aleatorias
  3. time - paquete de encabezado para funciones de tiempo

iostream se importa para las operaciones de entrada y salida en el programa. El otro paquete, cstdlib, se usa para operaciones de control básicas en programas C++.

El tercer paquete es el paquete tiempo que se utilizará para crear la semilla del programa.

Generar valores según la tirada de dados en C++

Un dado tiene 6 valores individuales. El papel del programa debe ser generar un número natural aleatorio dentro del rango, que puede repetirse en tiradas de dado posteriores, pero el resultado general debe parecer puramente aleatorio.

Se inicializan tres variables para encontrar el resultado. Las variables suelo y techo almacenan los valores más bajos y más altos del dado, y la variable resultado se utiliza para encontrar el número aleatorio.

int outcome;
int l_limit = 1;
int h_limit = 6;

El valor final se genera utilizando la función rand(), limitando el resultado dentro del rango superior e inferior.

outcome = rand() % (max - min + 1) + min;

Finalmente, se devuelve la variable roll.

int outcome;
int l_limit = 1;  // floor or lower limit of a die
int h_limit = 6;  // ceiling or higher limit of a die

outcome = rand() % (h_limit - l_limit + 1) + l_limit;

return outcome;

Genere una semilla usando el tiempo y muestre los resultados

El programa toma la hora actual dentro de la función srand() y la pasa a la función rand(). La aplicación utiliza la función rand() del método Droll() para encontrar números naturales dentro de los límites estipulados.

srand(time(0));

Una vez que se ha producido la semilla, se debe llamar al método Droll() y se debe imprimir el resultado.

Convencionalmente, tres tiradas de dados siempre se consideran un juego completo. Esta técnica se repite tres veces para verificar la aleatoriedad.

Tendremos que poner el método Droll() dentro de un bucle for y llamar tres veces dentro de la instrucción print. El resultado final es una matriz 3X3 de números pseudoaleatorios generados a partir de una tirada de dado.

for (int i = 0; i < 3; i++) {
  std::cout << Droll() << " ";
  std::cout << Droll() << " ";
  std::cout << Droll() << std::endl;
}

Pongamos todo junto dentro del programa y veamos los resultados.

#include <cstdlib>
#include <iostream>

#include "time.h"

int Droll() {
  int outcome;
  int l_limit = 1;  // floor or lower limit of a die
  int h_limit = 6;  // ceiling or higher limit of a die

  outcome = rand() % (h_limit - l_limit + 1) + l_limit;

  return outcome;
}

int main() {
  srand(time(0));
  for (int i = 0; i < 3; i++) {
    std::cout << Droll() << " ";
    std::cout << Droll() << " ";
    std::cout << Droll() << std::endl;
  }
}

Producción :

3 1 2
6 1 3
4 5 4

--------------------------------
Process exited after 0.00784 seconds with return value 0
Press any key to continue . . .

Conclusión

Este artículo explica los conceptos básicos de los generadores de pseudo números. Los lectores han visto los diferentes métodos para generar un número aleatorio y sus ventajas e inconvenientes.

Se proporciona un programa C++ para aclarar los conceptos sobre cómo se generan números aleatorios dentro del rango y cómo se puede imitar una tirada de dados usando un programa de computadora.

Artículo relacionado - C++ Random