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
cbaixe 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 intpara guardar a semente, que inicialmente deve ser negativa, por exemplo:long int semente = -1L; - Chame a função
ran1quantas 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 90baixe 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
ran1quantas vezes quiser, por exemplo:
REAL(8) :: aleatorio
aleatorio = ran1(semente)- Compile seu programa normalmente.