Partilhar via


<random>

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 mt19937 mecanismo com uniform_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:

  1. 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.

  2. Desempenho: a rapidez com que os números podem ser gerados e a quantidade de memória necessária. Quanto menor, melhor.

  3. 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_engine O mecanismo padrão.

    typedef mt19937 default_random_engine;
    
  • knuth_b Motor Knuth.

    typedef shuffle_order_engine<minstd_rand0, 256> knuth_b;
    
  • minstd_rand0 Motor padrão mínimo de 1988 (Lewis, Goodman e Miller, 1969).

    typedef linear_congruential_engine<unsigned int, 16807, 0, 2147483647> minstd_rand0;
    
  • minstd_rand Motor padrão minstd_rand0 mínimo atualizado (Park, Miller e Stockmeyer, 1993).

    typedef linear_congruential_engine<unsigned int, 48271, 0, 2147483647> minstd_rand;
    
  • mt19937 Motor 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_64 Motor 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;
    
  • ranlux24 Motor RANLUX de 24 bits (Martin Lüscher e Fred James, 1994).

    typedef discard_block_engine<ranlux24_base, 223, 23> ranlux24;
    
  • ranlux24_base Usado como base para ranlux24.

    typedef subtract_with_carry_engine<unsigned int, 24, 10, 24> ranlux24_base;
    
  • ranlux48 Motor RANLUX de 48 bits (Martin Lüscher e Fred James, 1994).

    typedef discard_block_engine<ranlux48_base, 389, 11> ranlux48;
    
  • ranlux48_base Usado como base para ranlux48.

    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.

[Modelos de mecanismo]

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 um short, int, long, , long long, unsigned shortunsigned intunsigned long, , ou unsigned long long.

  • UIntType indica unsigned short, unsigned int, unsigned long, ou unsigned long long.

  • RealType indica um float, double, ou long 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:

  • typedef numeric-type result_type é o tipo que é retornado pelo gerador operator(). O numeric-type é passado como um parâmetro de modelo na instanciação.

  • result_type operator() Retorna valores que são uniformemente distribuídos entre min() e max().

  • result_type min() Devolve o valor mínimo que é devolvido pelo gerador operator(). Os adaptadores do motor utilizam o resultado do motor de min() base.

  • result_type max() retorna o valor máximo retornado pelo gerador operator(). Quando result_type é um tipo max() integral (valor inteiro), é o valor máximo que pode realmente ser retornado (inclusive), quando result_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 de max() base.

  • void seed(result_type s) sementes o gerador com valor sde semente . Para mecanismos, a assinatura é void seed(result_type s = default_seed) para suporte a parâmetros padrão (adaptadores de mecanismo definem um separado void seed(), consulte a próxima subseção).

  • template <class Seq> void seed(Seq& q) semear o gerador usando um seed_seqSeqarquivo .

  • Um construtor explícito com argumento result_type x que cria um gerador semeado como se estivesse chamando seed(x).

  • Um construtor explícito com argumento seed_seq& seq que cria um gerador semeado como se estivesse chamando seed(seq).

  • void discard(unsigned long long count) efetivamente chama operator()count os 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:

  • typedef numeric-type result_type é o tipo que é retornado pelo operator(). O numeric-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, usando gen como 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, utilizando gen como fonte de valores aleatórios uniformemente distribuídos e a estrutura pdos parâmetros.

  • typedef unspecified-type param_type é o pacote de parâmetros opcionalmente passado para operator() 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() const Obté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 pelo operator().

  • result_type max() retorna o valor máximo retornado pelo operator(). Quando result_type é um tipo max() integral (valor inteiro), é o valor máximo que pode realmente ser retornado (inclusive), quando result_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 para operator() 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:

  • typedef distribution-type distribution_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.

Ver também

de referência de arquivos de cabeçalho