3.11.1 Um Gerador de Números Aleatórios Simples

Observação Antes de iniciar esta seção, deve ser vista a seção do compartilhamento de variáveis Module.

Em vários problemas computacionais é imprescindível a utilização de um gerador de números aleatórios. O propósito em geral é construir uma amostragem que possua algum tipo de ruido. Em outros casos como a técnica de Monte Carlo é muito importante que se utilize um bom gerador de números aleatórios.

Este tema é muito rico em discussões e temos livros específicos sobre geradores de números aleatórios, inclusive especificações e classes de geradores de números aleatórios. De fato o nosso propósito aqui não é estudar a construção de geradores de números aleatórios e sim a utilização deles, no entanto temos que nos atentar ao detalhe de sempre testarmos a qualidade dos geradores de números aleatórios. Um teste simples é verificar a média para uma amostragem dos números aleatórios gerados, em geral geradores de números aleatórios nos devolvem números $0 \leqslant n < 1$ a média de vários números gerados deve ser próximo de $0.5$. Outro teste bastante simples de se fazer é construir um histograma do números gerados, quando o número de sorteios tender para o infinito o histograma tem que mostrar um resultado constante.

Na linguagem específica o gerador de números aleatórios que iremos estudar é na verdade um pseudo gerador de números aleatórios pois utilizamos algoritmos, um modelo, para gerar esses números, mas como dito anteriormente sobre essa discussão é melhor conversar com algum especialista sobre o assunto.

Este algoritmo3.9 que veremos a seguir utiliza uma semente, um número inteiro positivo, para disparar o gerador de números aleatórios. Vale frisar que para uma semente sempre teremos a mesma sequência de números aleatórios. Não temos um números máximo de números aleatórios e isto irá depender do tipo de problema que está estudando ou ira resolver.

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! VARIAVEL N SEMPRE SERA COMPARTILHADA ENTRE AS SUBROTINAS
! QUE GERAM OS NUMEROS ALEATORIOS.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
module aleatorio
implicit none
integer, save :: n=6677
end module aleatorio
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! PROGRAMA QUE GERAM NUMEROS ALEATORIOS
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
program gna
implicit none
!
real :: media        ! MEDIA DOS NUMEROS ALEATORIOS
integer :: i,j       ! UTILIZADOS NOS DO'S
integer :: isemente  ! SEMENTE INICIAl
real :: nran         ! NUMERO ALEATORIO
real :: soma         ! SOMA DOS NUMEROS ALEATORIOS
!
write(*,*) 'Entre com a semente: '
read(*,*) isemente
!
! CHAMANDO A SUBROTINA SEMENTE
call semente(isemente)
!
write(*,*) '10 numeros randomicos'
do i=1, 10
        ! CHAMADA DO GERADOR DE NUM.ALEAT.
        call num_aleatorio(nran)
        write(*,500)nran
end do
!
!
write(*,*)'Media de 100 numeros aleatorios, de 5 sequencias de 100'
do j=1, 5
        soma = 0.
        do i=1,100
                call num_aleatorio(nran)
                soma = soma + nran
        end do
        media = soma / 100.0
        write(*,500) media  
end do
!
500 format(3x,f15.6)
stop
end program gna
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! GERA O NUMERO ALEATORIO
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
subroutine num_aleatorio(nran)
use aleatorio
implicit none
!
real, intent(out) :: nran
n = mod( 8127*n+28417 , 134453 )
nran = real(n) / 134453.0
!
end subroutine num_aleatorio
!
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! TRANSFORMA A SEMENTE EM UM NUMERO POSITIVO
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
subroutine semente(isemente)
use aleatorio
implicit none
integer, intent(in) :: isemente
!
n=abs(isemente)
!
end subroutine semente
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

A subrotina num_aleatorio utiliza a equação $n = MOD(8127*n + 28417 , 134453)$, lembremos que $MOD$ nos dá o resto da divisão de $8127*n + 28417$ por $134453$. O valor de n é atribuído através do número inteiro que digitamos dada pela variável isemente, o número n será base e a entrada do novo dará o número aleatório. O número aleatório de fato será por $nran = real(n) / 134453.0$. A idéia deste código é que o resto da divisão sempre será um número compreendido entre 0 e 134453 no qual será dividido pelo número 134453, assim o número randômico poderá estar compreendido entre $0 \leqslant n > 1$. Na tabela 3.8 temos a sequencia de 5 números aleatórios tendo como partida um valor da semente igual a 10. Pode ser feito esta sequência no caderno com um auxílio da calculadora, para a primeira linha veja qual o valor do resto para a divisão entre os números ( $8127*10 + 28417$) e $134453$ que deve ser igual ao valor de n, com o valor de n divida por $134453$, assim terá o valor de nran.


Tabela 3.8: Sequência de números aleatórios (nran) e do número que alimenta a equação dos números aleatórios (n).
  n nran            
1 109687 0.815784            
2 31276 0.232611            
3 92299 0.686462            
4 29103 0.216450            
5 45671 0.339672