Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Define facilidades para a geração de números aleatórios, permitindo a criação de números aleatórios uniformemente distribuídos.
Requerimentos
Cabeçalho: <random>
Espaço de nomes: std
Observação
A <random> biblioteca usa a #include <initializer_list> instrução.
Resumo
Um gerador de números aleatórios é um objeto que produz uma sequência de valores pseudoaleatórios. Um gerador que produz valores que são uniformemente distribuídos em um intervalo especificado é um Gerador de Número Aleatório Uniforme (URNG). Um modelo de classe projetado para funcionar como um URNG é referido como um mecanismo se essa classe tiver certas características comuns, que serão discutidas mais adiante neste artigo. Uma URNG pode ser — e geralmente é — combinada com uma distribuição passando a URNG como um argumento para a distribuição operator() para produzir valores que são distribuídos de uma maneira que é definida pela distribuição.
Esses links vão para as principais seções deste artigo:
Sugestões Rápidas
Aqui estão algumas dicas para ter em mente ao usar <random>:
Para a maioria das finalidades, as URNGs produzem bits brutos que devem ser moldados por distribuições. (Uma exceção notável a isso é
std::shuffle()porque ele usa um URNG diretamente.)Uma única instanciação de um URNG ou distribuição não pode ser chamada simultaneamente com segurança porque a execução de um URNG ou distribuição é uma operação de modificação. Para obter mais informações, consulte Segurança de thread na biblioteca padrão C++.
São fornecidos tipos predefinidos de vários motores; esta é a maneira preferida de criar um URNG se um mecanismo estiver sendo usado.
O emparelhamento mais útil para a maioria dos aplicativos é o
mt19937mecanismo comuniform_int_distribution, conforme mostrado no exemplo de código mais adiante neste artigo.
Há muitas opções para escolher no <random> cabeçalho, e qualquer uma delas é preferível à função rand()C Runtime desatualizada. Para obter informações sobre o que há de errado e rand() como <random> resolver essas deficiências, consulte este vídeo.
Exemplos
O exemplo de código a seguir mostra como gerar alguns números aleatórios, neste caso, cinco deles usando um gerador criado com semente não determinística.
#include <random>
#include <iostream>
using namespace std;
int main()
{
random_device rd; // non-deterministic generator
mt19937 gen(rd()); // to seed mersenne twister.
// replace the call to rd() with a
// constant value to get repeatable
// results.
for (int i = 0; i < 5; ++i) {
cout << gen() << " "; // print the raw output of the generator.
}
cout << endl;
}
2430338871 3531691818 2723770500 3252414483 3632920437
Embora estes sejam números aleatórios de alta qualidade e diferentes cada vez que este programa é executado, eles não estão necessariamente em um intervalo útil. Para controlar o intervalo, use uma distribuição uniforme como mostrado no código a seguir:
#include <random>
#include <iostream>
using namespace std;
int main()
{
random_device rd; // non-deterministic generator
mt19937 gen(rd()); // to seed mersenne twister.
uniform_int_distribution<> dist(1,6); // distribute results between 1 and 6 inclusive.
for (int i = 0; i < 5; ++i) {
cout << dist(gen) << " "; // pass the generator to the distribution.
}
cout << endl;
}
5 1 6 1 2
O próximo exemplo de código mostra um conjunto mais realista de casos de uso com geradores de números aleatórios uniformemente distribuídos embaralhando o conteúdo de um vetor e uma matriz.
// cl.exe /EHsc /nologo /W4 /MTd
#include <algorithm>
#include <array>
#include <iostream>
#include <random>
#include <string>
#include <vector>
#include <functional> // ref()
using namespace std;
template <typename C> void print(const C& c) {
for (const auto& e : c) {
cout << e << " ";
}
cout << endl;
}
template <class URNG>
void test(URNG& urng) {
// Uniform distribution used with a vector
// Distribution is [-5, 5] inclusive
uniform_int_distribution<int> dist(-5, 5);
vector<int> v;
for (int i = 0; i < 20; ++i) {
v.push_back(dist(urng));
}
cout << "Randomized vector: ";
print(v);
// Shuffle an array
// (Notice that shuffle() takes a URNG, not a distribution)
array<string, 26> arr = { { "H", "He", "Li", "Be", "B", "C", "N", "O", "F",
"Ne", "Na", "Mg", "Al", "Si", "P", "S", "Cl", "Ar", "K", "Ca", "Sc",
"Ti", "V", "Cr", "Mn", "Fe" } };
shuffle(arr.begin(), arr.end(), urng);
cout << "Randomized array: ";
print(arr);
cout << "--" << endl;
}
int main()
{
// First run: non-seedable, non-deterministic URNG random_device
// Slower but crypto-secure and non-repeatable.
random_device rd;
cout << "Using random_device URNG:" << endl;
test(rd);
// Second run: simple integer seed, repeatable results
cout << "Using constant-seed mersenne twister URNG:" << endl;
mt19937 engine1(12345);
test(engine1);
// Third run: random_device as a seed, different each run
// (Desirable for most purposes)
cout << "Using non-deterministic-seed mersenne twister URNG:" << endl;
mt19937 engine2(rd());
test(engine2);
// Fourth run: "warm-up" sequence as a seed, different each run
// (Advanced uses, allows more than 32 bits of randomness)
cout << "Using non-deterministic-seed \"warm-up\" sequence mersenne twister URNG:" << endl;
array<unsigned int, mt19937::state_size> seed_data;
generate_n(seed_data.begin(), seed_data.size(), ref(rd));
seed_seq seq(begin(seed_data), end(seed_data));
mt19937 engine3(seq);
test(engine3);
}
Using random_device URNG:
Randomized vector: 5 -4 2 3 0 5 -2 0 4 2 -1 2 -4 -3 1 4 4 1 2 -2
Randomized array: O Li V K C Ti N Mg Ne Sc Cl B Cr Mn Ca Al F P Na Be Si Ar Fe S He H
--
Using constant-seed mersenne twister URNG:
Randomized vector: 3 -1 -5 0 0 5 3 -4 -3 -4 1 -3 0 -3 -2 -4 5 1 -1 -1
Randomized array: Al O Ne Si Na Be C N Cr Mn H V F Sc Mg Fe K Ca S Ti B P Ar Cl Li He
--
Using non-deterministic-seed mersenne twister URNG:
Randomized vector: 5 -4 0 2 1 -2 4 4 -4 0 0 4 -5 4 -5 -1 -3 0 0 3
Randomized array: Si Fe Al Ar Na P B Sc H F Mg Li C Ti He N Mn Be O Ca Cr V K Ne Cl S
--
Using non-deterministic-seed "warm-up" sequence mersenne twister URNG:
Randomized vector: -1 3 -2 4 1 3 0 -5 5 -5 0 0 5 0 -3 3 -4 2 5 0
Randomized array: Si C Sc H Na O S Cr K Li Al Ti Cl B Mn He Fe Ne Be Ar V P Ca N Mg F
--
Esse código demonstra duas randomizações diferentes — randomizar um vetor de inteiros e embaralhar uma matriz de dados indexados — com uma função de modelo de teste. A primeira chamada para a função de teste usa o URNG random_devicecripto-seguro, não determinístico, não semeável e não repetível. A segunda execução de teste usa mersenne_twister_engine como URNG, com uma semente constante determinística de 32 bits, o que significa que os resultados são repetíveis. O terceiro teste executa sementes mersenne_twister_engine com um resultado não-determinístico de 32 bits de random_device. A quarta execução de teste expande isso usando uma sequência de sementes preenchida com random_device resultados, que efetivamente dá mais de 32 bits de aleatoriedade não determinística (mas ainda não cripto-segura). Para mais informações, continue a ler.
Listagem Categorizada
Geradores de números aleatórios uniformes
As URNGs são frequentemente descritas em termos destas propriedades:
Duração do período: quantas iterações são necessárias para repetir a sequência de números gerados. Quanto mais tempo, melhor.
Desempenho: a rapidez com que os números podem ser gerados e a quantidade de memória necessária. Quanto menor, melhor.
Qualidade: Quão próxima de números aleatórios verdadeiros é a sequência gerada. Isso é frequentemente chamado de "aleatoriedade".
As seções a seguir listam os geradores de números aleatórios uniformes (URNGs) fornecidos no <random> cabeçalho.
Gerador não-determinístico
random_device Classe
Gera uma sequência aleatória não determinística e criptograficamente segura usando um dispositivo externo. Geralmente usado para semear um motor. Baixo desempenho, muito alta qualidade. Para obter mais informações, consulte Comentários.
Tipo de motor defs com parâmetros predefinidos
Para instanciar motores e adaptadores de motor. Para obter mais informações, consulte Mecanismos e distribuições.
default_random_engineO mecanismo padrão.typedef mt19937 default_random_engine;knuth_bMotor Knuth.typedef shuffle_order_engine<minstd_rand0, 256> knuth_b;minstd_rand0Motor padrão mínimo de 1988 (Lewis, Goodman e Miller, 1969).typedef linear_congruential_engine<unsigned int, 16807, 0, 2147483647> minstd_rand0;minstd_randMotor padrãominstd_rand0mínimo atualizado (Park, Miller e Stockmeyer, 1993).typedef linear_congruential_engine<unsigned int, 48271, 0, 2147483647> minstd_rand;mt19937Motor twister Mersenne de 32 bits (Matsumoto e Nishimura, 1998).typedef mersenne_twister_engine< unsigned int, 32, 624, 397, 31, 0x9908b0df, 11, 0xffffffff, 7, 0x9d2c5680, 15, 0xefc60000, 18, 1812433253> mt19937;mt19937_64Motor twister Mersenne de 64 bits (Matsumoto e Nishimura, 2000).typedef mersenne_twister_engine< unsigned long long, 64, 312, 156, 31, 0xb5026f5aa96619e9ULL, 29, 0x5555555555555555ULL, 17, 0x71d67fffeda60000ULL, 37, 0xfff7eee000000000ULL, 43, 6364136223846793005ULL> mt19937_64;ranlux24Motor RANLUX de 24 bits (Martin Lüscher e Fred James, 1994).typedef discard_block_engine<ranlux24_base, 223, 23> ranlux24;ranlux24_baseUsado como base pararanlux24.typedef subtract_with_carry_engine<unsigned int, 24, 10, 24> ranlux24_base;ranlux48Motor RANLUX de 48 bits (Martin Lüscher e Fred James, 1994).typedef discard_block_engine<ranlux48_base, 389, 11> ranlux48;ranlux48_baseUsado como base pararanlux48.typedef subtract_with_carry_engine<unsigned long long, 48, 5, 12> ranlux48_base;
Modelos de motor
Os modelos de motor são usados como URNGs independentes ou como motores de base passados para adaptadores de motor. Normalmente, estes são instanciados com um tipo de motor predefinido e passados para uma distribuição. Para obter mais informações, consulte a seção Mecanismos e distribuições .
| Nome | Descrição |
|---|---|
linear_congruential_engine Classe |
Gera uma sequência aleatória usando o algoritmo congruencial linear. Mais simplista e de menor qualidade. |
mersenne_twister_engine Classe |
Gera uma sequência aleatória usando o algoritmo twister de Mersenne. Mais complexo, e é da mais alta qualidade, exceto para a classe random_device. Desempenho muito rápido. |
subtract_with_carry_engine Classe |
Gera uma sequência aleatória usando o algoritmo subtrair-com-carregar. Uma melhoria na linear_congruential_engine, mas muito menor qualidade e desempenho do que mersenne_twister_engine. |
Modelos de adaptador de motor
Os adaptadores de motor são modelos que adaptam outros motores (básicos). Normalmente, estes são instanciados com um tipo de motor predefinido e passados para uma distribuição. Para obter mais informações, consulte a seção Mecanismos e distribuições .
| Nome | Descrição |
|---|---|
discard_block_engine Classe |
Gera uma sequência aleatória descartando valores retornados por seu mecanismo base. |
independent_bits_engine Classe |
Gera uma sequência aleatória com um número especificado de bits reempacotando bits a partir dos valores retornados por seu mecanismo base. |
shuffle_order_engine Classe |
Gera uma sequência aleatória reordenando os valores retornados de seu mecanismo base. |
Distribuições de números aleatórios
As seções a seguir listam as distribuições fornecidas no <random> cabeçalho. As distribuições são um mecanismo de pós-processamento, geralmente usando a saída URNG como entrada e distribuindo a saída por uma função de densidade de probabilidade estatística definida. Para obter mais informações, consulte a seção Mecanismos e distribuições .
Distribuições uniformes
| Nome | Descrição |
|---|---|
uniform_int_distribution Classe |
Produz uma distribuição uniforme de valor inteiro em um intervalo no intervalo fechado [a, b] (inclusive-inclusive). |
uniform_real_distribution Classe |
Produz uma distribuição uniforme de valor real (ponto flutuante) através de um intervalo no intervalo semiaberto [a, b) (inclusive-exclusivo). |
generate_canonical |
Produz uma distribuição uniforme de valores reais (ponto flutuante) de uma determinada precisão em [0, 1) (inclusive exclusivo). |
[Distribuições de números aleatórios]
Distribuições Bernoulli
| Nome | Descrição |
|---|---|
bernoulli_distribution Classe |
Produz uma distribuição Bernoulli de bool valores. |
binomial_distribution Classe |
Produz uma distribuição binomial de valores inteiros. |
geometric_distribution Classe |
Produz uma distribuição geométrica de valores inteiros. |
negative_binomial_distribution Classe |
Produz uma distribuição binomial negativa de valores inteiros. |
[Distribuições de números aleatórios]
Distribuições normais
| Nome | Descrição |
|---|---|
cauchy_distribution Classe |
Produz uma distribuição de Cauchy de valores reais (ponto flutuante). |
chi_squared_distribution Classe |
Produz uma distribuição qui-quadrada de valores reais (ponto flutuante). |
fisher_f_distribution Classe |
Produz uma distribuição F (também conhecida como distribuição F de Snedecor ou distribuição Fisher-Snedecor) de valores reais (ponto flutuante). |
lognormal_distribution Classe |
Produz uma distribuição log-normal de valores reais (ponto flutuante). |
normal_distribution Classe |
Produz uma distribuição normal (gaussiana) de valores reais (ponto flutuante). |
student_t_distribution Classe |
Produz uma distribuição t de valores reais (ponto flutuante) de Student. |
[Distribuições de números aleatórios]
Distribuições Poisson
| Nome | Descrição |
|---|---|
exponential_distribution Classe |
Produz uma distribuição exponencial de valores reais (ponto flutuante). |
extreme_value_distribution Classe |
Produz uma distribuição de valor extrema de valores reais (ponto flutuante). |
gamma_distribution Classe |
Produz uma distribuição gama de valores reais (ponto flutuante). |
poisson_distribution Classe |
Produz uma distribuição de Poisson de valores inteiros. |
weibull_distribution Classe |
Produz uma distribuição Weibull de valores reais (ponto flutuante). |
[Distribuições de números aleatórios]
Distribuições de amostragem
| Nome | Descrição |
|---|---|
discrete_distribution Classe |
Produz uma distribuição inteira discreta. |
piecewise_constant_distribution Classe |
Produz uma distribuição constante por partes de valores reais (ponto flutuante). |
piecewise_linear_distribution Classe |
Produz uma distribuição linear por partes de valores reais (ponto flutuante). |
[Distribuições de números aleatórios]
Funções de utilidade
Esta seção lista as funções de utilidade geral fornecidas no <random> cabeçalho.
| Nome | Descrição |
|---|---|
seed_seq Classe |
Gera uma sequência de sementes mexidas não tendenciosas. Usado para evitar a replicação de fluxos variáveis aleatórios. Útil quando muitos URNGs são instanciados a partir de mecanismos. |
Operadores
Esta seção lista os <random> operadores fornecidos no cabeçalho.
| Nome | Descrição |
|---|---|
operator== |
Testa se a URNG do lado esquerdo do operador é igual ao motor do lado direito. |
operator!= |
Testa se a URNG do lado esquerdo do operador não é igual ao motor do lado direito. |
operator<< |
Grava informações de estado em um fluxo. |
operator>> |
Extrai informações de estado de um fluxo. |
Motores e distribuições
Consulte as seções a seguir para obter informações sobre cada uma dessas categorias de modelo de classe definidas em <random>. Ambas as categorias de modelo de classe usam um tipo como argumento e usam nomes de parâmetros de modelo compartilhados para descrever as propriedades do tipo que são permitidas como um tipo de argumento real, da seguinte maneira:
IntTypeindica umshort,int,long, ,long long,unsigned shortunsigned intunsigned long, , ouunsigned long long.UIntTypeindicaunsigned short,unsigned int,unsigned long, ouunsigned long long.RealTypeindica umfloat,double, oulong double.
Furgão
Engine Templates e Engine Adaptor Templates são modelos cujos parâmetros personalizam o gerador criado.
Um mecanismo é uma classe ou modelo de classe cujas instâncias (geradores) atuam como uma fonte de números aleatórios uniformemente distribuídos entre um valor mínimo e máximo. Um adaptador de motor fornece uma sequência de valores que têm diferentes propriedades de aleatoriedade pegando valores produzidos por algum outro mecanismo de números aleatórios e aplicando um algoritmo de algum tipo a esses valores.
Cada motor e adaptador de motor tem os seguintes membros:
typedefnumeric-typeresult_typeé o tipo que é retornado pelo geradoroperator(). Onumeric-typeé passado como um parâmetro de modelo na instanciação.result_type operator()Retorna valores que são uniformemente distribuídos entremin()emax().result_type min()Devolve o valor mínimo que é devolvido pelo geradoroperator(). Os adaptadores do motor utilizam o resultado do motor demin()base.result_type max()retorna o valor máximo retornado pelo geradoroperator(). Quandoresult_typeé um tipomax()integral (valor inteiro), é o valor máximo que pode realmente ser retornado (inclusive), quandoresult_typeé um tipo de ponto flutuante (valor real),max()é o menor valor maior do que todos os valores que podem ser retornados (não incluído). Os adaptadores do motor utilizam o resultado do motor demax()base.void seed(result_type s)sementes o gerador com valorsde semente . Para mecanismos, a assinatura évoid seed(result_type s = default_seed)para suporte a parâmetros padrão (adaptadores de mecanismo definem um separadovoid seed(), consulte a próxima subseção).template <class Seq> void seed(Seq& q)semear o gerador usando umseed_seqSeqarquivo .Um construtor explícito com argumento
result_type xque cria um gerador semeado como se estivesse chamandoseed(x).Um construtor explícito com argumento
seed_seq& seqque cria um gerador semeado como se estivesse chamandoseed(seq).void discard(unsigned long long count)efetivamente chamaoperator()countos tempos e descarta cada valor.
Os adaptadores de motor suportam adicionalmente estes membros (Engine é o primeiro parâmetro de modelo de um adaptador de motor, designando o tipo de motor de base):
Um construtor padrão para inicializar o gerador como se fosse do construtor padrão do mecanismo base.
Um construtor explícito com argumento
const Engine& eng. Isso é para suportar a construção de cópia usando o motor base.Um construtor explícito com argumento
Engine&& eng. Isto é para apoiar a construção de movimento usando o motor de base.void seed()que inicializa o gerador com o valor de semente padrão do mecanismo base.const Engine& base()função de propriedade que retorna o mecanismo base que foi usado para construir o gerador.
Cada mecanismo mantém um estado que determina a sequência de valores que serão gerados por chamadas subsequentes para operator(). Os estados de dois geradores instanciados a partir de motores do mesmo tipo podem ser comparados usando operator== e operator!=. Se os dois estados se compararem como iguais, eles gerarão a mesma sequência de valores. O estado de um objeto pode ser salvo em um fluxo como uma sequência de valores não assinados de 32 bits usando o operator<< do gerador. O Estado não se muda salvando-o. Um estado salvo pode ser lido no gerador instanciado a partir de um mecanismo do mesmo tipo usando operator>>.
Distribuições
Uma Distribuição de Número Aleatório é uma classe ou modelo de classe cujas instâncias transformam um fluxo de números aleatórios uniformemente distribuídos obtidos de um mecanismo em um fluxo de números aleatórios que têm uma distribuição específica. Cada distribuição tem os seguintes membros:
typedefnumeric-typeresult_typeé o tipo que é retornado pelooperator(). Onumeric-typeé passado como um parâmetro de modelo na instanciação.template <class URNG> result_type operator()(URNG& gen)Retorna valores que são distribuídos de acordo com a definição da distribuição, usandogencomo fonte de valores aleatórios uniformemente distribuídos e os parâmetros armazenados da distribuição.template <class URNG> result_type operator()(URNG& gen, param_type p)Devolve valores distribuídos de acordo com a definição da distribuição, utilizandogencomo fonte de valores aleatórios uniformemente distribuídos e a estruturapdos parâmetros.typedefunspecified-typeparam_typeé o pacote de parâmetros opcionalmente passado paraoperator()e é usado no lugar dos parâmetros armazenados para gerar seu valor de retorno.Um
const param&construtor inicializa os parâmetros armazenados a partir de seu argumento.param_type param() constObtém os parâmetros armazenados.void param(const param_type&)Define os parâmetros armazenados a partir de seu argumento.result_type min()Devolve o valor mínimo que é devolvido pelooperator().result_type max()retorna o valor máximo retornado pelooperator(). Quandoresult_typeé um tipomax()integral (valor inteiro), é o valor máximo que pode realmente ser retornado (inclusive), quandoresult_typeé um tipo de ponto flutuante (valor real),max()é o menor valor maior do que todos os valores que podem ser retornados (não incluído).void reset()Descarta quaisquer valores armazenados em cache, para que o resultado da próxima chamada paraoperator()não dependa de quaisquer valores obtidos do mecanismo antes da chamada.
Uma estrutura de parâmetros é um objeto que armazena todos os parâmetros necessários para uma distribuição. Contém:
typedefdistribution-typedistribution_type, que é o tipo da sua distribuição.Um ou mais construtores que usam as mesmas listas de parâmetros que os construtores de distribuição assumem.
As mesmas funções de acesso a parâmetros que a distribuição.
Operadores de comparação de igualdade e desigualdade.
Para obter mais informações, consulte os subtópicos de referência abaixo deste, vinculados anteriormente neste artigo.
Observações
Há dois URNGs altamente úteis no Visual Studio—mt19937 e random_device—como mostrado nesta tabela de comparação:
| URNG | Rápido | Cripto-seguro | Semeável | Determinística |
|---|---|---|---|---|
mt19937 |
Sim | Não | Sim | Sim* |
random_device |
Não | Sim | Não | Não |
* Quando fornecido com uma semente conhecida.
Embora o padrão ISO C++ não exija random_device ser criptograficamente seguro, no Visual Studio ele é implementado para ser criptograficamente seguro. (O termo "criptograficamente seguro" não implica garantias, mas refere-se a um nível mínimo de entropia – e, portanto, o nível de previsibilidade – que um determinado algoritmo de aleatorização fornece. Para obter mais informações, consulte o artigo da Wikipedia Cryptographically secure pseudorandom number generator.) Como a norma ISO C++ não exige isso, outras plataformas podem ser implementadas random_device como um simples gerador de números pseudoaleatórios (não criptograficamente seguro) e podem ser adequadas apenas como fonte de sementes para outro gerador. Verifique a documentação dessas plataformas ao usar random_device em código multiplataforma.
Por definição, random_device os resultados não são reprodutíveis, e um efeito colateral é que pode ser significativamente mais lento do que outras URNGs. A maioria dos aplicativos que não precisam ser criptograficamente seguros usam mt19937 ou um mecanismo semelhante, embora você queira semeá-lo com uma chamada para random_device, conforme mostrado no exemplo de código.