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

4 minutos de lectura

avatar de usuario
Hannun Yassir

Esta es la primera vez que pruebo números aleatorios con C (echo de menos 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 agrego srand(/*somevalue/*) antes de for círculo. ¿Alguien puede explicar por qué?

  • Como un nodo lateral: las implementaciones de rand() suelen ser bastante malas. Esto significa ciclos de repetición cortos y números aleatorios de baja calidad. Así que usaría un PRNG de terceros y no el incluido en su tiempo de ejecución.

    – CodesInChaos

    12/10/2010 a las 20:09

  • srand(): ¿por qué llamarlo solo una vez?

    – phuclv

    30 de abril de 2017 a las 9:58

Si recuerdo la cita del trabajo seminal de Knuth “El arte de la programación de computadoras” al comienzo del capítulo sobre Generación de números aleatorios, dice así:

“Cualquiera que intente generar números aleatorios por medios matemáticos está, técnicamente hablando, en un estado de pecado”.

En pocas palabras, los generadores de números aleatorios de stock son algoritmos, matemáticos y 100% predecibles. En realidad, esto es algo bueno en muchas situaciones, donde es deseable una secuencia repetible de números “aleatorios”, por ejemplo, para ciertos ejercicios estadísticos, donde no desea el “bamboleo” en los resultados que introducen datos verdaderamente aleatorios gracias a efectos de agrupamiento.

Aunque obtener bits de datos “aleatorios” del hardware de la computadora es una segunda alternativa popular, tampoco es realmente aleatorio, aunque cuanto más complejo es el entorno operativo, más posibilidades hay de aleatoriedad o, al menos, imprevisibilidad.

Los generadores de datos verdaderamente aleatorios tienden a buscar fuentes externas. La desintegración radiactiva es una de las favoritas, al igual que el comportamiento de los cuásares. Cualquier cosa cuyas raíces estén en los efectos cuánticos es efectivamente aleatoria, para disgusto de Einstein.

  • Como lo consigo getpid()? ¿Necesito alguna biblioteca especial?

    – Hola

    21 de abril de 2018 a las 13:11

  • @Hola #include <unistd.h>

    – ggorlen

    26 oct 2021 a las 21:20

avatar de usuario
Aditya Sehgal

Para citar de hombre rand :

La función srand() establece su argumento como la 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() asume la semilla como 1 (cada vez en su caso) y con el mismo valor semilla, rand() producirá la misma secuencia de números.

avatar de usuario
coste y flete

Hay muchas respuestas aquí, pero nadie parece tener De Verdad explicó por qué rand() siempre genera la misma secuencia dada la misma semilla, o incluso lo que la semilla realmente está haciendo. Así que aquí va.

La función rand() mantiene un estado interno. Conceptualmente, podría pensar en esto como una variable global de algún tipo llamada rand_state. Cada vez que llamas a rand(), hace dos cosas. Usa el estado existente para calcular un nuevo estado, y usa el nuevo estado para calcular un número para regresar a usted:

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 puede ver que cada vez que llama a rand(), hará que rand_state se mueva un paso a lo largo de una ruta predeterminada. Los valores aleatorios que ve solo se basan en dónde se encuentra a lo largo de 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, calcule_next_state(), calcule_return_value() y generate_random_state() pueden variar de una plataforma a otra, pero por lo general son bastante simples.

Puede ver a partir de esto que cada vez que se inicia su programa, rand_state comenzará en INITIAL_STATE (que es equivalente a generate_random_state(1)), razón por la cual siempre obtiene la misma secuencia si no usa srand().

avatar de usuario
Josu Goñi

Rand no te da un número aleatorio. Te da el siguiente número en una secuencia generada por un pseudoaleatorio generador de números Para obtener una secuencia diferente cada vez que inicie su programa, debe inicializar el algoritmo llamando srand.

Una forma (muy mala) de hacerlo es pasándole la hora actual:

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

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

¿Por qué esta es una mala manera? Porque un generador de números pseudoaleatorios es tan bueno como su semilla, y la semilla debe ser impredecible. Por eso es posible que necesite una mejor fuente de entropía, como leer de /dev/urandom.

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad