Gerador de números aleatórios
Um gerador de números aleatórios é um rotina que gera números pseudo-aleatórios a partir de uma parâmetro de entrada chamado de semente. Em geral o número gerado é um número real no intervalo $[0,1)$. O papél da semente é fazer com que o gerador retorne sempre os mesmos números se for iniciado com a mesma semente. Por exemplo, se você executa o gerador duas vezes sendo que na primeira você usou a semente igual a $-1$ e em cada vez obteve, respectivamente, os números $a_1$ e $a_2$ então se você reiniciar a gerador com a mesma semente e executar-lo duas vezes então irá obter novamente os mesmos valores $a_1$ e $a_2$.
Dizemos que os números são pseudo-aleatórios pois na prática é impossível gerar números verdadeiramente aleatórios sem uso de alguma “moeda quântica”, entretanto a correlação entre os números gerados por uma bom gerador não é forte o suficiente para interferir em cálculos físicos, o que já nos basta. Apresentarei aqui a rotina ran1 retirada do livro numerical recipes com pequenas alterações.
A rotina ran1:
Usaremos uma variável inteira chamada semente
para, adivinhem, guardar a semente. Ao chamar a ran1
pela primeira vez em um programa, semente
deverá ser um valor negativo. ran1
irá alterar o valor de semente
para um número positivo assim da próxima vez que você chamar ran1
ela entenderá que não está sendo inicializada e irá gerar um número aleatório sem correlação com o anterior. Por causa disso acho interessante usar uma variável semente0
para a semente propriamente dita e semente1
para usar como argumento para ran1
onde, no começo, semente1=semente0
dessa forma não perdemos a informação da semente que utilizamos para inicializar o gerador.
O número aleatório p
gerado tem precisão dupla então não tente guardalo em uma variável inteira sem converter.
Suponha que queremos guardar na variável de precisão dupla p
um número aleatório no intervalo $[x_0, x_1)$, para isso faça:
-
p = ran1(semente1)
- Como $p\in[0, 1)$ multiplicamos ele pelo comprimento do intervalo:
p = p*(x1-x0)
- Dessa forma temos $p\in[0, x_1-x_0)$. Agora some $x_0$ a $p$:
p = p+x0
- Temos, finalmente, $p\in[x_0, x_1)$ como queríamos. De forma mais reduzida, pode-se fazer tudo em um cálculo só quando se chama o gerador, da forma:
p = ran1(semente1) * (x1-x0) + x0
ran1 em C
Usar a ran1
em c
é fácil. Simplesmente faça:
- No diretório do seu programa em
c
baixe o arquivo ran1.c digitando no terminalwget -O ran1.c https://github.com/ismaeldamiao/avulsos/raw/master/c/rotinas/ran1.c
- Utilize a seguinte macro, ela irá incluir a funcão
double ran1(long int *)
no seu programa:#include "ran1.c"
- Declare uma variável
long int
para guardar a semente, que inicialmente deve ser negativa, por exemplo:long int semente = -1L;
- Chame a função
ran1
quantas vezes quiser, lembrando de indicar a região da memória da semente, por exemplo:double aleatorio = ran1(&semente);
- Compile seu programa normalmente.
ran1 em FORTRAN 90
Usar a ran1
em FORTRAN 90
é fácil. Simplesmente faça:
- No diretório do seu programa em
FORTRAN 90
baixe o arquivo ran1.90 digitando no terminalwget -O https://github.com/ismaeldamiao/avulsos/raw/master/fortran/rotinas/ran1.f90
- Utilize a linha
INCLUDE "ran1.f90"
dentro doCONTAINS
, ela irá incluir a funcãoREAL(8) ran1(INTEGER(8))
no seu programa. Deve ficar mais ou menos assim:
PROGRAM SeuPrograma
! Seu codigo
CONTAINS
INCLUDE "ran1.f90"
END PROGRAM SeuPrograma
- Declare uma variável
INTEGER(8)
para guardar a semente, que inicialmente deve ser negativa, por exemplo:INTEGER(8) :: semente = -1
- Chame a função
ran1
quantas vezes quiser, por exemplo:
REAL(8) :: aleatorio
aleatorio = ran1(semente)
- Compile seu programa normalmente.