¿Por qué siempre obtengo la misma secuencia de números aleatorios con rand()?

Resuelto Hannoun Yassir asked hace 15 años • 12 respuestas

Esta es la primera vez que intento números aleatorios con C (extraño C#). Aquí está mi código:

int i, j = 0;
for(i = 0; i <= 10; i++) {
    j = rand();
    printf("j = %d\n", j);
}

Con este código, obtengo la misma secuencia cada vez que ejecuto el código. Pero genera diferentes secuencias aleatorias si las agrego srand(/*somevalue/*)antes del forciclo. ¿Alguien puede explicar por qué?

Hannoun Yassir avatar Jul 10 '09 17:07 Hannoun Yassir
Aceptado

Hay que sembrarlo. Sembrarlo con el tiempo es una buena idea:

srand()

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main ()
{
  srand ( time(NULL) );
  printf ("Random Number: %d\n", rand() %100);
  return 0;
}

Obtienes la misma secuencia porque rand()se inicializa automáticamente con un valor de 1 si no llamas srand().

Editar

debido a comentarios

rand()devolverá un número entre 0 y RAND_MAX(definido en la biblioteca estándar). Usando el operador de módulo ( %) se obtiene el resto de la división rand() / 100. Esto forzará que el número aleatorio esté dentro del rango 0-99. Por ejemplo, para obtener un número aleatorio en el rango de 0 a 999 aplicaríamos rand() % 1000.

kjfletch avatar Jul 10 '2009 10:07 kjfletch

rand()devuelve números pseudoaleatorios . Genera números basados ​​en un algoritmo determinado.

El punto de partida de ese algoritmo es siempre el mismo, por lo que verás la misma secuencia generada para cada invocación. Esto es útil cuando necesita verificar el comportamiento y la coherencia de su programa.

Puede configurar la "semilla" del generador aleatorio con la srandfunción (solo llame sranduna vez en un programa). Una forma común de obtener diferentes secuencias del rand()generador es configurar la semilla en la hora actual o la identificación del proceso:

srand(time(NULL));o srand(getpid());al inicio del programa.

Generar aleatoriedad real es muy, muy difícil para una computadora, pero para trabajos prácticos no relacionados con las criptomonedas, un algoritmo que intenta distribuir uniformemente las secuencias generadas funciona bien.

nos avatar Jul 10 '2009 10:07 nos

Para citar a man rand :

La función srand() establece su argumento como semilla para una nueva secuencia de enteros pseudoaleatorios que devolverá rand(). Estas secuencias se pueden repetir llamando a srand() con el mismo valor inicial.

Si no se proporciona ningún valor inicial, la función rand() se inicializa automáticamente con un valor de 1.

Entonces, sin valor inicial, rand()se asume que la semilla es 1 (siempre en su caso) y con el mismo valor inicial, rand()producirá la misma secuencia de números.

Aditya Sehgal avatar Jul 10 '2009 10:07 Aditya Sehgal

Hay muchas respuestas aquí, pero nadie parece haber explicado realmente por qué rand() siempre genera la misma secuencia dada la misma semilla, o incluso qué está haciendo realmente la semilla. Así que ahí va.

La función rand() mantiene un estado interno. Conceptualmente, se podría considerar esto como una variable global de algún tipo llamada rand_state. Cada vez que llamas a rand(), hace dos cosas. Utiliza el estado existente para calcular un nuevo estado y utiliza el nuevo estado para calcular un número que se le devolverá:

state_t rand_state = INITIAL_STATE;

state_t calculate_next_state(state_t s);
int calculate_return_value(state_t s);

int rand(void)
{
    rand_state = calculate_next_state(rand_state);
    return calculate_return_value(rand_state);
}

Ahora puedes ver que cada vez que llamas a rand(), hará que rand_state avance un paso a lo largo de una ruta predeterminada. Los valores aleatorios que ves se basan únicamente en dónde te encuentras en ese camino, por lo que también seguirán una secuencia predeterminada.

Ahora aquí es donde entra en juego srand(). Te permite saltar a un punto diferente en el camino:

state_t generate_random_state(unsigned int seed);

void srand(unsigned int seed)
{
    rand_state = generate_random_state(seed);
}

Los detalles exactos de state_t, calcular_next_state(), calcular_return_value() y generate_random_state() pueden variar de una plataforma a otra, pero normalmente son bastante simples.

Puedes ver en esto que cada vez que se inicia tu programa, rand_state comenzará en INITIAL_STATE (que es equivalente a generate_random_state(1)), razón por la cual siempre obtienes la misma secuencia si no usas srand().

caf avatar Jul 10 '2009 11:07 caf