Experiências, Lógica

Números “aleatórios” – Random

Você já se perguntou como o Math.random() gera um número aleatório ? Já? Bom, eu me perguntava bastante. Tanto que um dia resolvi revirar o que havia por trás dele. Isso já faz algum tempo, mas de qualquer forma, é algo interessante pra postar aqui.

Antes de mais nada não podemos descrever esses números como aleatórios ou randômicos porque é 100% previsível o número que o Math.random() vai gerar. Tá, tudo bem. Pra quem não se apega a detalhes e acha que isso é apenas semântica, vai em frente e chama isso de aleatório. Mas eles não são! São pseudoaleatórios. “Pseudo” porque são previsíveis como já falei. Como assim previsíveis? Veja. Em computação, existem os chamados “Pseudo Random number generators” ou geradores de números pseudo-aleatórios. Esses são baseados em uma equação que, recebendo como parâmetro um valor numérico, retorna uma série numérica. Os números que compõem essa série são normalmente bem diferentes uns dos outros (primos, ímpares, primos entre si, múltiplos de 7, próprio zero e assim por diante), o que podemos dizer que a equação gera números randômicos. O problema é que com o tempo, essa série começa a se repetir.

Mas… peraí! É previsível o número que o Math.random() vai gerar? Hã… sim! Ora, é baseado numa equação. E java.util.Random utiliza LCG  (Linear congruential generator):

 

Equação LCG

Equação LCG

Obviamente existem outras equações pra gerar essas sequências. Inclusive Von Neumann mesmo inventou uma (não muito boa por sinal).

Vamos ver na prática agora, como o Random gera a mesma sequência “aleatória” numa aplicação bem simples:

<code>

</p>

<pre>import java.util.Random;

public class GeradorAleatorio {

    private Random random;

    public GeradorAleatorio(long semente) {
         random = new Random(semente);
     }

     public int gerarInt() {
          return random.nextInt();
     }

     public long gerarLong() {
          return random.nextLong();
     }

     public double gerarDouble() {
          return random.nextDouble();
     }

     public static void main(String[] args) {
           GeradorAleatorio gerador =
           new GeradorAleatorio(10);
           long l = gerador.gerarLong();
           System.out.println(l);
      }
}

</code>

Pode rodar o código quantas vezes quiser. A sequência gerada sempre será “-4972683369271453960” seguido de “4755622236989466036“. Como o Random trata pra te entregar um valor double mais “bonitinho” é outra história.

Enfim, a questão é que a gente acabou de ver que esses números são sempre os mesmos pra o mesmo valor inicial passado (ou seed – semente). Daí surge a pergunta: “Como gerar números imprevisíveis?” Bom, existe uma técnica bem comum que é passar o System.currentTimeMillis() como seed ou valor inicial. Como esse valor corresponde ao número de milissegundos passados desde 1970 pra o tempo atual, esse valor irá variar numa amplitude maior ainda. Tornando-o estatisticamente imprevisível.

<code>
    GeradorAleatorio gerador =
    new GeradorAleatorio(System.currentTimeMillis());
    long l = gerador.gerarLong(); 
    System.out.println("O long aleatório foi: " + l);

</code>
Agora pode rodar o código quantas vezes quiser que o resultado será sempre diferente. Note que em teoria, o número sorteado ainda é previsível. Imagine que o mundo congelou no momento que a semente é passada para o construtor da classe Random e você pôde ver que número foi esse. Jogando ele na equação, você poderia prever com 100% de certeza que número seria sorteado. Mas enquanto o mundo não congelar tendenciosamente para alguns, o truque está seguro.

public class GeradorAleatorio {

 

private Random random;

 

public GeradorAleatorio(long semente) {

random = new Random(semente);

}

 

public int gerarInt() {

return random.nextInt();

}

 

public long gerarLong() {

return random.nextLong();

}

 

public double gerarDouble() {

return random.nextDouble();

}

 

public static void main(String[] args) {

GeradorAleatorio gerador = new GeradorAleatorio(System.currentTimeMillis());

long l = gerador.gerarLong();

System.out.println(l);

}

 

}

Padrão

3 comentários sobre “Números “aleatórios” – Random

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s