2
respostas

Rand executado duas vezes no programa

Olá,
Testando as funções rand() e srand(), escrevi o seguinte código:

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

int main() {
    srand(time(0));
    int i=rand();
    int j=rand();
    printf("\n%d %d\n", i, j);
}

Ao executar o programa repetidas vezes, observei que o segundo número impresso varia muito entre uma execução e outra. Porém, o primeiro número tem uma variação pequena e crescente de, aproximadamente, 3 ou 4 a cada segundo passado entre uma execução do programa e outra.
Apesar de os dois usarem a função time(0) como seed do número randômico, apenas um deles aparenta ser realmente randômico.
Como se explica isso? Seria importante para saber evitar o problema.

Garanta sua matrícula hoje e ganhe + 2 meses grátis

Continue sua jornada tech com ainda mais tempo para aprender e evoluir

Quero aproveitar agora
2 respostas

Só para atualizar:
Mudei o código para que ele redefina o valor das variáveis para novos números randômicos e os imprimisse novamente. Apenas o primeiro número impresso tem a aparência estranha que descrevi acima. Os outros três números aparentam ser completamente aleatórios.

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

int main() {
    srand(time(0));
    int i=rand();
    int j=rand();
    printf("\n%d %d\n", i, j);
    i=rand();
    j=rand();
    printf("\n%d %d\n", i, j);
}

Oi, Pedro! Tudo bem?

O comportamento “estranho” do primeiro rand() vem do fato de você semear com time(0), que tem resolução de 1 segundo. O primeiro valor gerado após srand(seed) é determinístico e muito correlacionado com o seed; como entre execuções o seed muda de +1 (próximo segundo), o primeiro rand() tende a variar pouco e de forma previsível. Já o segundo rand() (e os subsequentes) avançam o estado do gerador e diluem essa correlação, parecendo mais “randômicos”.

Faça assim para evitar o problema:

  1. Semeie uma única vez por execução e nunca antes de cada número.
  2. Descarte alguns valores iniciais (warm-up) após srand(...).
  3. Se quiser melhorar a entropia do seed, combine time(0) com PID ou algum contador; e, quando possível, prefira um gerador melhor que rand().

Veja este exemplo:


#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#ifdef _WIN32
  #include <process.h>  // _getpid
  #define GETPID _getpid
#else
  #include <unistd.h>   // getpid
  #define GETPID getpid
#endif

int main(void) {
    // 1) semente única por execução, misturando segundos com PID para variar entre execuções no mesmo segundo
    unsigned int seed = (unsigned int)time(NULL) ^ (unsigned int)GETPID();
    srand(seed);

    // 2) warm-up: descarta os primeiros valores que são mais correlacionados com a semente
    for (int k = 0; k < 8; ++k) (void)rand();

    // 3) use rand normalmente
    int a = rand();
    int b = rand();
    int c = rand();
    int d = rand();

    printf("seed=%u\\n", seed);
    printf("%d %d %d %d\\n", a, b, c, d);
    return 0;
}

Pontos importantes:

  • Não chame srand(...) mais de uma vez no programa (semeie só no início).
  • Se rodar o binário várias vezes dentro do mesmo segundo, time(0) sozinho pode gerar valores iguais; a mistura com PID ajuda.
  • Para aplicações sérias, troque rand() por um gerador melhor (ex.: PCG, arc4random() em sistemas BSD/macOS, getrandom()//dev/urandom em Linux, BCryptGenRandom/rand_s no Windows). Para o curso, o warm-up já resolve a percepção de “incrementos pequenos”.

Fico à disposição. Abraços e bons estudos!

Caso este post tenha lhe ajudado, por favor, marcar como solucionado ✓.