Por que eu sempre obtenho a mesma sequência de números randoms com rand ()?

Esta é a primeira vez que estou tentando números randoms com C (sinto falta de C #). Aqui está o meu código:

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

Com este código, recebo a mesma sequência toda vez que executo o código. Mas ele gera seqüências aleatórias diferentes se eu adicionar srand(/*somevalue/*) antes do loop for . Alguém pode explicar por quê?

Você tem que semear. Semeando com o tempo é uma boa ideia:

srand()

 #include  #include  #include  

Você obtém a mesma sequência porque rand () é automaticamente propagado com o valor a 1 se você não chamar srand ().

Editar

Devido a comentários

rand() retornará um número entre 0 e RAND_MAX (definido na biblioteca padrão). Usando o operador de módulo ( % ) dá o resto da divisão rand()/100 . Isso forçará o número random a estar no intervalo de 0 a 99. Por exemplo, para obter um número random no intervalo de 0 a 999, aplicaríamos rand()%1000 .

rand () retorna números pseudo-randoms . Ele gera números baseados em um determinado algoritmo. O ponto inicial desse algoritmo é sempre o mesmo, então você verá a mesma sequência gerada para cada chamada. Isso é útil quando você precisa verificar o comportamento e a consistência do seu programa.

Você pode definir a “semente” do gerador random com a function srand (somente chame srand uma vez em um programa) Uma maneira comum de obter sequências diferentes do gerador rand () é definir a semente para a hora atual ou o id de o processo:

srand (hora (NULL)); ou srand (getpid ()); no início do programa.

Gerar aleatoriedade real é muito difícil para um computador, mas para um trabalho prático não relacionado a criptografia, um algoritmo que tenta distribuir uniformemente as seqüências geradas funciona bem.

Para citar o homem rand :

A function srand () define seu argumento como a semente para uma nova seqüência de inteiros pseudo-randoms a serem retornados por rand (). Essas seqüências são repetíveis chamando srand () com o mesmo valor de semente.

Se nenhum valor de semente for fornecido, a function rand () será automaticamente propagada com um valor de 1.

Portanto, sem valor de semente, rand () assume a semente como 1 (toda vez no seu caso) e com o mesmo valor de semente, rand () produzirá a mesma seqüência de números.

Se eu me lembro da citação do trabalho seminal de Knuth “A arte da programação de computadores” no início do capítulo sobre geração de números randoms, é assim:

“Qualquer um que tente gerar números randoms por meios matemáticos é, tecnicamente falando, em estado de pecado”.

Simplificando, os geradores de números randoms são algoritmos, matemáticos e 100% previsíveis. Isto é realmente uma coisa boa em muitas situações, onde uma sequência repetitiva de números “randoms” é desejável – por exemplo, para certos exercícios estatísticos, onde você não quer a “oscilação” em resultados que dados verdadeiramente randoms introduzem graças a efeitos de agrupamento.

Embora pegar bits de dados “randoms” do hardware do computador seja uma segunda alternativa popular, também não é verdadeiramente random – embora quanto mais complexo o ambiente operacional, mais possibilidades de aleatoriedade – ou pelo menos imprevisibilidade.

Geradores de dados verdadeiramente randoms tendem a procurar fonts externas. O decaimento radioativo é o favorito, assim como o comportamento dos quasares. Qualquer coisa cujas raízes estejam em efeitos quânticos é efetivamente random – para grande aborrecimento de Einstein.

Há muitas respostas aqui, mas ninguém parece ter realmente explicado porque é que rand () sempre gera a mesma sequência dada a mesma semente – ou mesmo o que a semente está realmente fazendo. Então aqui vai.

A function rand () mantém um estado interno. Conceitualmente, você poderia pensar nisso como uma variável global de algum tipo chamado rand_state. Cada vez que você chama rand (), ele faz duas coisas. Ele usa o estado existente para calcular um novo estado e usa o novo estado para calcular um número para retornar a você:

 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); } 

Agora você pode ver que cada vez que você chamar rand (), ele fará rand_state mover um passo ao longo de um caminho pré-determinado. Os valores randoms que você vê são apenas baseados em onde você está nesse caminho, então eles também seguem uma sequência pré-determinada.

Agora é aqui que vem o srand (). Ele permite que você pule para um ponto diferente no caminho:

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

Os detalhes exatos de state_t, calculate_next_state (), calculate_return_value () e generate_random_state () podem variar de plataforma para plataforma, mas geralmente são bem simples.

Você pode ver a partir disso que toda vez que seu programa iniciar, o rand_state começará em INITIAL_STATE (que é equivalente a generate_random_state (1)) – e é por isso que você sempre obterá a mesma sequência se você não usar srand ().

Geradores de números randoms não são realmente randoms, eles gostam que a maioria dos softwares é completamente previsível. O que o rand faz é criar um número pseudo-random diferente cada vez que é chamado Um, que parece ser random. Para usá-lo corretamente, você precisa dar um ponto de partida diferente.

 #include  #include  #include  

Isto é de http://www.acm.uiuc.edu/webmonkeys/book/c_guide/2.13.html#rand :

Declaração:

 void srand(unsigned int seed); 

Esta function semeia o gerador de números randoms usado pela function rand. Semear a semente com a mesma semente fará com que rand retorne a mesma sequência de números pseudo-randoms. Se srand não for chamado, rand age como se srand (1) fosse chamado.

rand () retorna o próximo (pseudo) número random em uma série. O que está acontecendo é que você tem a mesma série toda vez que é executado (padrão ‘1’). Para propagar uma nova série, você deve chamar srand () antes de começar a chamar rand ().

Se você quiser algo random o tempo todo, você pode tentar:

 srand (time (0)); 

chame srand(sameSeed) antes de chamar rand() . Mais detalhes aqui .

Semeando o rand()

 void srand (unsigned int seed) 

Esta function estabelece a semente como a semente para uma nova série de números pseudo-randoms. Se você chamar rand antes que uma semente tenha sido estabelecida com srand, ela usará o valor 1 como uma semente padrão.

Para produzir uma série pseudo-aleatória diferente toda vez que seu programa for executado, faça srand (time (0))

Nenhum de vocês está respondendo a pergunta dele.

com este código eu recebo a mesma sequencia toda vez que o código mas gera seqüências aleatórias se eu adicionar srand (/ somevalue /) antes do loop for. Alguém pode explicar por quê?

Pelo que meu professor me disse, ele é usado se você quiser ter certeza de que seu código está funcionando corretamente e ver se há algo errado ou se você pode mudar alguma coisa.

BTW: O fato de que rand NÃO é random (PRNG = PSEUDO Random Number Generator, onde pseudo é a palavra chave!) Pode ser muito útil.

Se o mesmo algoritmo for usado em computadores em uma rede e se alguns dados (por exemplo, estado do jogo) forem calculados usando números “randoms”, e se o código em todas as máquinas for sincronizado, a chamada rand será chamada no mesmo local / tempo por todos os clientes, você pode reduzir a carga da rede regenerando dados / events / qualquer localmente.

Pseudo-random é uma coisa adorável. 🙂


PS Se você já confiar em rand (om) sendo sincronizado, no entanto, você deve codificar sua própria implementação – outra plataforma e outras diferenças vão estragar sua diversão. 🙂