C ++ número aleatório entre 0 e 1

C ++ número aleatório entre 0 e 1
Um número aleatório é gerado dentro de um intervalo, de um número mínimo a um número máximo. Suponha que esses números mínimos e máximos sejam maiores que 1. Deixe o número gerado dentro do intervalo ser num. Deixe o número mínimo ser min e o número máximo seja máximo. Com estes, para converter o número para entre 0 e 1, use a fórmula:
random_number = (num - min)/(max - min)

Random_Number agora deve estar entre 0 e 1.
As próximas perguntas são como gerar números aleatórios e como decidir min e max. De fato, números aleatórios, conforme descrito pela especificação C ++ 20, são na verdade números pseudo-aleatórios. A especificação C ++ 20 fornece um guia para produzir números verdadeiramente aleatórios (números aleatórios não determinísticos). O problema com esse gerador de números verdadeiramente aleatório é que a responsabilidade do compilador, ou o programador, é fornecer o algoritmo ao que é considerado geração de números aleatórios não determinísticos. Este artigo não aborda números aleatórios não determinísticos.

Os números pseudo-aleatórios são gerados em uma sequência (uma ordem) de números, que parecem números aleatórios. A geração de um número aleatório precisa do que é chamado de semente. A semente é algum valor inicial. Este artigo explica o básico da geração de números aleatórios em C ++ 20. Se o número resultante for maior que 1, será reduzido entre 0 e 1, usando a fórmula acima. A biblioteca C ++ deve ser incluída no programa para ter uma sequência de números aleatórios ou aleatórios.

Conteúdo do artigo

  • Distribuições
  • linear_congruential_engine
  • default_random_engine
  • Classes de distribuição de números aleatórios
  • Melhor número aleatório
  • Conclusão

Distribuições
Distribuição uniforme

Uma distribuição uniforme é aquela em que a probabilidade de um número é um do número total de números na sequência. Considere a seguinte sequência:

0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100

Se esses onze números forem uma sequência de números aleatórios, cada número apareceu uma vez nas onze ocorrências. Isso significa que é uma distribuição uniforme. Na prática, nem todos podem aparecer uma vez. Um ou dois ou três podem aparecer mais de uma vez, e eles não apareceriam em ordem regular.

Se o número aleatório retornado for 40, o programa terá que converter o número aleatório para entre 0 e 1 usando

random_number = (40 - 0)/(100 - 0)
= 4/10 = 0.4

Aqui, Num é 40; min é 0 e max é 100.

Distribuição binomial

A distribuição binomial não é uma distribuição uniforme. "Bi", o prefixo do binomial, significa dois. O número de valores na distribuição binomial é representado por t em c++. Se os números de BI preocupados com a distribuição forem 2 e 3, e se t for 1, a sequência será:

2, 3

Se t é 2 para os mesmos números de BI (2 e 3), então a sequência se torna,

4, 12, 9

Se t é 3 para os mesmos números de BI (2 e 3), então a sequência se torna,

8, 36, 54, 27

Se t é 4 para os mesmos números de BI (2 e 3), então a sequência se torna,

16, 96, 216, 216, 81

t é um número inteiro positivo que pode ser superior a 4. Para cada valor de t, existem elementos T+1 na sequência. Uma sequência depende dos números de BI escolhidos e do valor de t. Os números de BI podem ser qualquer par, e.g., 13 e 17. A soma dos números de BI também é importante. Uma sequência é desenvolvida a partir do que é conhecido como Teorema Binomial.

Existem outras distribuições na biblioteca aleatória em C++.

linear_congruential_engine

Existem vários motores de números aleatórios em C++. linear_congruential_engine é um deles. Este motor pega uma semente, multiplica -a com um multiplicador e adiciona um número constante C ao produto para ter o primeiro número aleatório. O primeiro número aleatório se torna a nova semente. Esta nova semente é multiplicada pelo mesmo 'a', cujo produto é adicionado ao mesmo C, para ter o segundo número aleatório. Este segundo número aleatório se torna a nova semente para o próximo número aleatório. Este procedimento é repetido para tantos números aleatórios quanto exigido pelo programador.

A semente aqui tem o papel de um índice. A semente padrão é 1.

Uma sintaxe para o linear_congruential_engine é:

linear_congruential_enginelce

lce é o nome da escolha do programador. Esta sintaxe usa a semente padrão de 1. O primeiro parâmetro de modelo aqui deve ser especializado com “INT não assinado”. O segundo e o terceiro devem ter os valores reais de 'a' e c. O quarto deve ter o valor real do número aleatório máximo esperado, mais 1.

Supondo que seja necessária uma semente do valor 2, a sintaxe seria:

linear_congruential_engineLCE (2)

Observe a semente entre parênteses logo após o LCE.

O programa a seguir ilustra o uso de linear_congruential_engine, com a semente padrão de 1:

#incluir
#incluir
usando namespace std;
int main ()

linear_congruential_enginelce;
cout <cout <cout <cout <cout <cout <cout <cout <retornar 0;

A saída é:

4
13
40
121
364
0
499

Observe a maneira como o objeto LCE para o motor foi instanciado. Aqui, 'a' é 3, c é 1 e o máximo espera atingir o número, m é 500. M é realmente um módulo - veja mais tarde. lce (), como usado aqui, não é um construtor. É um operador que retorna o próximo número aleatório necessário para o motor na sequência de saída. Min para este esquema é 0 e o máximo é 499, e eles podem ser usados ​​para converter um número retornado entre 0 e 1 - veja abaixo.

O primeiro número aleatório retornado é 4. É igual a 1 x 3 + 1 = 4. 4 se torna a nova semente. O próximo número aleatório é 13, que é igual a 4 x 3 + 1 = 13. 13 se torna a nova semente. O próximo número aleatório é 40, que é igual a 13 x 3 + 1 = 40. Dessa maneira, os números aleatórios seguintes são 121 e 364.

O código a seguir ilustra o uso de linear_congruential_engine, com uma semente de 2:

linear_congruential_enginelce (2);
cout <cout <cout <cout <cout <cout <cout <cout <

A saída é:

7
22
67
202
607
0
999

O número aleatório máximo esperado aqui é 1000. Min para este esquema ainda é 0, e Max agora é 999, e eles podem ser usados ​​para converter um número retornado entre 0 e 1 - veja abaixo

O primeiro número aleatório retornado é 7. É igual a 2 x 3 + 1 = 7. 7 se torna a nova semente. O próximo número aleatório é 22, que é igual a 7 x 3 + 1 = 22. 22 se torna a nova semente. O próximo número aleatório é 67, que é igual a 22 x 3 + 1 = 67. Dessa forma, os números aleatórios seguintes são 202 e 607.

O código a seguir usa a fórmula acima para produzir um número aleatório entre 0 e 1, para este mecanismo:

linear_congruential_enginelce (2);
não assinado int num = lce (); // Número aleatório normal
não assinado int min = lce.min ();
não assinado int max = lce.max ();
float random_number = ((float) (num - min))/((float) (max - min));
cout <

A saída é:

0.00700701

Aqui, num é 7, e assim

random_number = (7 - 0)/(999 - 0) = 7/999 = 0.00700701 arredondado para 8 lugares decimais.

linear_congruential_engine não é o único mecanismo especializado na biblioteca aleatória; há outros.

default_random_engine

Isso é como um motor de uso geral. Produz números aleatórios. A ordem de sequência não é garantida para não ser determinada. No entanto, a ordem provavelmente não é conhecida pelo programador. As duas linhas a seguir mostram como este mecanismo pode ser usado:

Random_Device Rd;
default_random_engine Eng (rd ());

Random_device é uma classe da qual RD foi instanciado. Observe os parênteses para RD nas listas de argumentos do mecanismo. Um distribuidor precisa deste mecanismo para sua operação - veja abaixo.

Classes de distribuição de números aleatórios
uniform_int_distribution

uniform_int_distribution
A probabilidade de que qualquer número ocorra seja 1 dividido pelo número total de números para esta classe. Por exemplo, se houver dez números de saída possíveis, a probabilidade de cada número que está sendo exibido é 1/10. O código a seguir ilustra o seguinte:

Random_Device Rd;
default_random_engine Eng (rd ());
uniform_int_distributiondist (3, 12);
cout <cout <

A saída do computador do autor é:

9 8 3 5 12
7 4 11 7 6

Infelizmente, 7 apareceu duas vezes à custa de 10. Os argumentos de Dist são os números 3 e 13 inclusive (dez números inteiros consecutivos). Dist (Eng) é um operador que retorna o próximo número. Ele usa o motor. Observe o uso da especialização do modelo int.

Não há necessidade de procurar num, min e max para este caso e depois usar a fórmula acima para obter um número entre 0 e 1. Isso ocorre porque há um flutuador equivalente a essa classe que usa a especialização do float. A saída não será a mesma para cada execução.

uniform_real_distribution

uniform_real_distribution é semelhante ao uniforme_int_distribution. Com ele, para obter um número entre 0 e 1, basta usar 0 e 1 como os argumentos. O código a seguir ilustra o seguinte:

Random_Device Rd;
default_random_engine Eng (rd ());
uniform_real_distributiondist (0, 1);
cout <cout <

A saída do computador do autor é:

0.384051 0.745187 0.364855 0.122008 0.580874
0.745765 0.0737481 0.48356 0.184848 0.745821

Observe o uso da especialização do modelo de flutuação. A saída não será a mesma para cada execução.

distribuição binomial

Com esta distribuição, a probabilidade de cada número de saída não é a mesma. binomial_distribution foi ilustrado acima. O código a seguir mostra como usar a Binomial_distribution para produzir 10 números aleatórios:

Random_Device Rd;
default_random_engine Eng (rd ());
distribuição binomialdist (10);
cout <cout <

A saída do computador do autor é:

5 3 5 5 7
6 6 5 8 3

A saída não será a mesma para cada execução. A especialização do modelo usada aqui é int.

O código a seguir usa a fórmula acima para produzir um número aleatório entre 0 e 1, para esta distribuição:

Random_Device Rd;
default_random_engine Eng (rd ());
distribuição binomialdist (10);
não assinado int num = dist (Eng); // Número aleatório normal
não assinado int min = dist.min ();
não assinado int max = dist.max ();
cout <cout <cout <cout <float random_number = ((float) (num - min))/((float) (max - min));
cout <

A saída do computador do autor é:

0
10
7
0.7

Melhor número aleatório

O número de segundos desde a época da UNIX pode ser usada como semente. Torna -se difícil para o hacker conhecer a semente. O programa a seguir ilustra isso com o linear_congruential_engine:

#incluir
#incluir
#incluir
usando namespace std;
int main ()

const auto p1 = crono :: system_clock :: agora ();
não assinado int semente = crono :: duration_cast(p1.time_since_epoch ()).contar();
linear_congruential_enginelce (semente);
cout <cout <cout <cout <retornar 0;

A saída do computador do autor é:

91 274 823 470 411
0
999

Observe que a biblioteca Chrono foi incluída. A saída é diferente para cada execução.

Conclusão

A maneira mais fácil de ter um número aleatório entre 0 e 1 é usar o Random_device, o Default_random_engine e o Uniform_real_distribution (com argumentos 0 e 1). Qualquer outro motor ou distribuição utilizada pode precisar da fórmula, random_number = (num - min)/(máx - min).