1. Números pseudoaleatórios

Às vezes, um programador enfrenta tarefas aparentemente simples: "selecionar um filme aleatório de uma determinada lista", "escolher um vencedor da loteria", "embaralhar a lista de reprodução quando o usuário balançar o smartphone", "escolher um número aleatório para criptografar uma mensagem" , etc. Em cada caso, o desenvolvedor faz uma pergunta lógica: como obter um número aleatório?

Na verdade, obter um número verdadeiramente aleatório é bastante difícil de fazer. Na verdade, é tão difícil que coprocessadores matemáticos especiais são embutidos em alguns computadores para gerar números que satisfaçam todos os requisitos para a verdadeira aleatoriedade.

Os programadores criaram sua própria solução: números pseudo-aleatórios . Os números pseudoaleatórios são uma espécie de sequência, cujos números parecem ser aleatórios. No entanto, ao realizar uma análise cuidadosa, um especialista pode encontrar certos padrões na sequência. Esses números não são adequados para criptografar documentos secretos, mas são suficientes para simular o lançamento de um dado em um jogo.

Existem muitos algoritmos para gerar uma sequência de números pseudoaleatórios. Quase todos eles geram o próximo número aleatório com base no número anterior e alguns números auxiliares adicionais.

Por exemplo, este programa exibirá 1000números não repetidos:

public class Main
{
   public static int a = 41;
   public static int c = 11119;
   public static int m = 11113;
   public static int seed = 1;

   public static int getNextRandom()
   {
     seed = (a * seed + c) % m;
     return seed;
   }

   public static void main(String[] args)
   {
     for (int i = 0; i < 1000; i++)
     {
       System.out.println(getNextRandom());
     }
   }
}

A propósito, não estamos falando de números pseudo-aleatórios aqui. Estamos falando de uma sequência de números pseudoaleatórios. Olhando para um único número, é impossível dizer se é aleatório ou não.

De fato, existem várias maneiras de obter um número aleatório:

public static int getRandomNumber()
{
   return 4; // Here's a random number (we got it by rolling a die)
}

2.Math.random()

Em Java, a Mathclasse possui um método especial que retorna um número aleatório. E como você pode imaginar, o método é chamado random. Em geral, aqui está a aparência de chamar esse método:

Math.random()

Este método não aceita parâmetros e retorna um número real pseudo-aleatório no intervalo de 0a 1. O número 1 em si não está incluído no intervalo.

Exemplo:

Código Saída do console
public class Main
{
   public static void main(String[] args)
   {
     for (int i = 0; i < 10; i++)
     {
       System.out.println(Math.random());
     }
   }
} 
0.9703753971734451
0.09979423801773157
0.994048474709053
0.2852203204171295
0.13551248551226025
0.3128547131272822
0.5342480554101412
0.6817369932044817
0.1840767788961758
0.06969563435451254

Mas e se esse método não for exatamente o que você precisa? Suponha que você queira escrever um programa que simule o lançamento de um dado de seis lados. Como você obtém inteiros aleatórios no intervalo 1..6, em vez de números reais no intervalo 0..1?

Na verdade, é bem simples.

Primeiro, você precisa mapear o intervalo [0, 1)em [0, 6). Para fazer isso, basta multiplicar o resultado retornado por random()por 6. Claro, para obter números inteiros, você precisa arredondar para cima:

Código Saída do console
public class Main
{
   public static int getRandomDieNumber()
   {
      return (int) (Math.random() * 6);
   }

   public static void main(String[] args)
   {
      for (int i = 0; i < 10; i++)
      {
         int x = getRandomDieNumber();
         System.out.println(x);
      }
   }
}
5
2
3
3
2
4
1
1
5
0

O getRandomDieNumber()retorna um número inteiro aleatório no intervalo 0..5inclusive. Mas não será um número no conjunto 1, 2, 3, 4, 5, 6. Será um número no conjunto 0, 1, 2, 3, 4, 5.

Se o que você precisa são números no conjunto 1, 2, 3, 4, 5, 6, basta adicionar um aos números aleatórios:

Código Saída do console
public class Main
{
   public static int getRandomDieNumber()
   {
      return (int) (Math.random() * 6) + 1;
   }

   public static void main(String[] args)
   {
     for (int i = 0; i < 10; i++)
     {
       int x = getRandomDieNumber();
       System.out.println(x);
     }
   }
}
3
2
1
3
6
5
6
1
6
6

Agora isso é perfeito!



3. Randomclasse

Java tem uma classe especial Randomque encapsula uma sequência de números pseudo-aleatórios. Você pode criar vários objetos da Randomclasse. Cada um desses objetos gerará sua própria sequência de números pseudo-aleatórios.

Esta é uma classe super interessante com muitos métodos interessantes. Vamos começar com o mais simples.

double nextDouble()

Este método retorna um número real aleatório no intervalo 0.0- 1.0. É muito parecido com o Math.random()método. E não é de admirar, já que o Math.random()método simplesmente chama o nextDouble()método em um Randomobjeto.

float nextFloat()

Este método é muito semelhante ao nextDouble()método, mas o número aleatório retornado é um float. Também está no intervalo 0.0- 1.0. E, como sempre em Java, o intervalo não inclui o 1.0próprio número.

Random r = new Random();
float f = r.nextFloat();

int nextInt(int max)

Este método retorna um número inteiro aleatório no intervalo [0, max). 0está incluído no intervalo, mas maxnão está.

Em outras palavras, se você quiser obter um número aleatório no conjunto 1, 2, 3, 4, 5, 6, precisará adicionar um ao número aleatório retornado:

Random r = new Random();
int x = r.nextInt(6) + 1;

int nextInt()

Este método é semelhante ao anterior, mas não recebe nenhum parâmetro. Então, qual é o intervalo para seus valores de retorno? De -2 billiona +2 billion.

Bem, para ser preciso, de -2147483648para +2147483647.

long nextLong()

Este método é semelhante ao nextInt()método, mas o valor de retorno cairá em algum lugar em todo o intervalo possível de longs.

boolean nextBoolean()

Este método retorna um booleanvalor aleatório: falseou true. Isso é muito conveniente quando você precisa obter uma longa sequência de valores booleanos aleatórios.

void nextBytes(byte[] data)

Este método não retorna nada (já que o tipo de retorno é void). Em vez disso, ele preenche a matriz passada com valores aleatórios. Isso é muito útil quando você precisa de um buffer grande preenchido com dados aleatórios.

double nextGaussian()

Este método retorna um número real aleatório no intervalo 0.0- 1.0. No entanto, os números não são distribuídos uniformemente nesse intervalo. Em vez disso, eles seguem uma distribuição normal .

Valores próximos ao meio do intervalo ( 0.5) ocorrerão com mais frequência do que valores nas extremidades do intervalo.

classe aleatória

No nosso caso, o pico da distribuição de valor estará em0.5