Para fazer o EP1 você não precisa ler este texto. Você pode simplesmente usar a "receita" dada no EP. A leitura do texto a seguir é destinada aos alunos que estiverem mais curiosos sobre o assunto.

Números pseudo-aleatórios

Geração de números aleatórios é um assunto amplamente estudado e que tem aplicações em várias áreas. Números aleatórios usados em computadores comuns não são verdadeiramente "aleatórios" sendo por isso chamados de números pseudo-aleatórios. Existem máquinas especialmente construídas para a geração de números aleatórios.

Existem vários algoritmos para geração de números pseudo-aleatórios em computadores. Os algoritmos são chamados de geradores de números aleatórios.

Um dos mais conhecidos geradores de números aleatórios é baseado no chamado método das congruências lineares. Dado um número inicial X0, conhecido como semente, o próximo número da sequência é dado por

X1 = (aX0 +b) % m.

Em geral, o número Xi+1 é obtido a partir do número Xi pela fórmula

Xi+1 = (aXi +b) % m,
onde a, b e m são números criteriosamente escolhidos. O operador % indica resto da divisão. Os números assim gerados estão entre 0 e m-1.

Por exemplo, para a=7, b=1, m = 13 e X0 = 3, a sequência de números gerada é

9 12 7 11 0 1 8 5 10 6 4 3 9 . . .   
Uma forma de usar esse gerador de números aleatórios para gerar números entre 1 e k, é usar a fórmula
Yi = 1 + (Xi % k).

Para a sequência do exemplo mostrado acima, os números gerados entre 1 e k=5 seriam

5 3 3 2 1 2 4 1 1 2 5 4 5 . . .   

Um pouco mais sobre números aleatórios

Para os mais curiosos, segue uma pequena explicação bem simplificada sobre o fenômeno de "os números estão repetindo", que ocorre ao usarmos algum gerador de números aleatórios.

Um gerador de número aleatórios é uma função que devolve os números de uma sequência, um número a cada chamada da função. Suponha que, através de várias chamadas da função, a sequência

X0 X1 X2 X3 X4 . . .
é obtida e suponha que o gerador usa o método das congruências lineares através da expressão
Xi+1 = (aXi +b) % m,
onde a, b e m são constantes inteiras.

Considere, para simplificar muito as coisas, um gerador de números aleatórios que devolve números inteiros entre 0 e 6. Suponha que a sequência devolvida por esse tal gerador é

1 6 0 5 3 3 4 2 1 2 1 6 0 5 3 3 4 2 1 2 1 6 . . .

Com isto queremos dizer que o primeiro valor obtido pelo gerador é o número 1, o segundo valor obtido é o número 6, e assim por diante. Reparem que a sequência começa a se repetir a partir de um certo ponto; notem o


1 6 . . . 1 6 . . .
Há quem chame esse tipo de sequência de cíclica. A posição na sequência a partir da qual o gerador começa a devolver os números é determinada por um valor, a chamada semente do gerador, que pode ou não ser fornecida ao gerador para que ele faça o seu serviço. Por exemplo, digamos que seja fornecido ao nosso gerador imaginário o número 1234 como semente, a partir daí ele pode, digamos, devolver os números abaixo, na ordem em que aparecem,
3 3 4 2 1 2 1 6 0 5 3 3 4 2 1 2 1 6 0 5 3 3 . . .

Já, se fornecermos a semente 4321, o gerador talvez passe a devolver os números

4 2 1 2 1 6 0 5 3 3 4 2 1 2 1 6  1 6 0 5 3 3 4 2

    Resumindo, a semente só determina o ponto exato do início da sequência cíclica a partir do qual os números são devolvidos pelo gerador.

De volta ao EP1, o comando

srand(time(NULL));
inicializa a semente do gerador com o valor do relógio do computador. Se usarmos o comando
srand(1234);
a semente do gerador é inicializada com 1234 e, cada vez que o programa é executado, a sequência devolvida pelo gerador será precisamente a mesma. Isso pode ser útil para achar erros no programa.

Curiosidade:

O gerador usado pelo Python é o Mersenne Twister, e não congruências lineares, porém as mesmas explicações acima se aplicam a ele também.