
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é?
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.

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.

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().

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
.
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