Números aleatórios são muito importantes em várias áreas da informática, como jogos, simulações e na geração de chaves criptográficas. Um gerador de números pseudoaleatórios (PRNG - Pseudo Random Number Generator) é um algoritmo que gera uma sequência de valores aparentemente aleatórios. A sequência de números gerada por um PRNG não é realmente aleatória, porque pode ser reproduzida caso seja usado o mesmo valor inicial, usualmente chamado de “semente” (seed).1)
Uma das abordagens mais simples para a geração de números pseudoaleatórios são os geradores congruentes lineares (LCG), que são definidos através da seguinte fórmula:
xi+1 = (A · xi + C) mod M
onde “x0” é o valor inicial (semente), A e C são parâmetros inteiros, M é o tamanho do espaço de valores aleatórios possíveis e “mod” é o resto da divisão inteira.
Por exemplo, escolhendo-se A=40.692, C=127, M=10.000.000 e x0=0, será gerada a seguinte sequência de números pseudoaleatórios:
x0 = 0
x1 = 127
x2 = 5168011
x3 = 6703739
x4 = 8547515
x5 = 5480507
x6 = 2790971
x7 = 192059
x8 = 5264955
x9 = 1548987
…
Construa uma biblioteca LC-Random para gerar números inteiros pseudoaleatórios usando o algoritmo de congruência linear; a interface dessa biblioteca é definida pelo seguinte arquivo de cabeçalho (que não deve ser alterado):
// ATENCAO: ESTE ARQUIVO NAO DEVE SER ALTERADO! #ifndef __LCRANDOM__ #define __LCRANDOM__ // calcula e devolve um valor pseudoaleatório unsigned long lcrandom () ; // define o valor inicial (semente) da sequência de aleatórios // (inicialmente zero (0) por default void lcrandom_seed (unsigned long s) ; // informa o valor máximo que pode ser gerado (o mínimo é sempre zero) unsigned long lcrandom_max () ; // modifica os parâmetros da equação do gerador; por default // devem ser usados: A=40.692, C=127 e M=10.000.000 void lcrandom_parms (unsigned long A, unsigned long C, unsigned long M) ; #endif
lcrandom_parms
não seja invocada, a implementação deve usar os valores default dos parâmetros A, C e M definidos no exemplo acima.
Dicas para a implementação:
lcrandom.c
.printf
, scanf
, etc) deve ser chamada dentro da implementação de suas funções (a não ser para produzir eventuais mensagens de erro).A distribuição dos valores produzidos por um gerador de números aleatórios pode ser avaliada visualmente através de um histograma2).
Escreva um programa C para gerar um histograma dos valores aleatórios produzidos por sua biblioteca.
Para isso:
lcrandom() % 100
);
Exemplo simplificado de histograma em modo texto (cada *
vale 2 unidades):
0 10 20 30 40 50 60 70 80 90 100 +----+----+----+----+----+----+----+----+----+----+ 0 |***************************** 1 |************************************************** 2 |**************************************** 3 |****************************************** 4 |*********************************** 5 |******************************* 6 |**************************** 7 |****************************** ...| (linhas omitidas) 98 |********************************** 99 |*********************************************** +----+----+----+----+----+----+----+----+----+----+
O período de um PRNG corresponde à quantidade de valores gerados por ele antes de começar a repeti-los, para uma dada semente. Por exemplo, para uma semente x0=0, um PRNG gera a seguinte sequência, cujo período é 16 (pois são gerados 16 valores distintos antes de repetir o 78):
0 2233 491 11 7219 7801 31 446 9876 831 6159 43259 63 38321 1126 43674 7801 31 446 9876 831 …
Escreva um programa C para calcular o período do gerador implementado em sua biblioteca, a partir de x0=0.
Repita o cálculo do histograma e do período usando valores melhores para os parâmetros A, C e M do gerador: A = 1.103.515.245, C = 12.345 e M = 2.147.483.648 (231) M = 1.073.741.824 (230) - valores inspirados de LCG.
relocation truncated to fit: R_X86_64_PC32 against symbol …
ao compilar seu código, experimente usar as opções -fPIC
ou -mcmodel=medium
na linha de compilação. Esses erros podem ocorrer no cálculo do período, caso um vetor muito grande.
Arquivos a entregar ao professor:
lcrandom.c
: implementação das funções do gerador de aleatórios;histograma-1.c
: implementação do histograma do gerador com os valores default de A, C e M;histograma-2.c
: idem, com os valores melhores de A, C e M;periodo-1.c
: implementação do cálculo de período do gerador com os valores default de A, C e M;periodo-2.c
: idem, com os valores melhores de A, C e M.
-Wall
e resolver todos os warnings, pois eles penalizam a nota.