Como o título sugere, estou tentando descobrir uma maneira de gerar números aleatórios usando a nova <random>
biblioteca C ++ 11 . Eu tentei com este código:
std::default_random_engine generator;
std::uniform_real_distribution<double> uniform_distance(1, 10.001);
O problema com o código que tenho é que sempre que eu o compilo e o executo, ele sempre gera os mesmos números. Então, minha pergunta é que outras funções da biblioteca aleatória podem realizar isso enquanto são verdadeiramente aleatórias?
Para meu caso de uso específico, eu estava tentando obter um valor dentro do intervalo [1, 10]
std::mt19937
como motor, a menos que você tenha um bom motivo para não fazê-lo. E a distribuição é um intervalo fechado nas duas extremidades.std::uniform_int_distribution
, que está fechado nas duas extremidades.Respostas:
Stephan T. Lavavej (stl) da Microsoft fez uma palestra no Going Native sobre como usar as novas funções aleatórias do C ++ 11 e por que não usá-las
rand()
. Nele, ele incluiu um slide que basicamente resolve sua pergunta. Copiei o código desse slide abaixo.Você pode ver a palestra completa aqui: http://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful
Usamos
random_device
uma vez para propagar o gerador de número aleatório chamadomt
.random_device()
é mais lento quemt19937
, mas não precisa ser propagado porque solicita dados aleatórios do seu sistema operacional (que serão originários de vários locais, como o RdRand, por exemplo).Olhando para esta pergunta / resposta , parece que
uniform_real_distribution
retorna um número no intervalo[a, b)
, onde você deseja[a, b]
. Para fazer isso, nossouniform_real_distibution
deve realmente parecer com:fonte
default_random_engine
, de acordo com c ++ cartilha é aquele que a implementação considerou mais útildefault_random_engine
exista.std::default_container
, espero que não haja pessoas, considerando-se os programadores que não sabem as diferenças, uma grande quantidade de linguagens de script tem uma estrutura padrão tipo de mapa, que pode ser implementado em toda uma variedade de maneiras que o usuário pode não sabernextafter
chamada é um exagero para a maioria dos aplicativos. As chances de umdouble
pouso aleatório exatamente no terminal são tão minúsculas que não há diferença prática entre incluí-lo e excluí-lo.std::vector
analogia não funciona aqui porquestd::vector
é realmente um bom padrão devido ao cache da CPU. Ele até superastd::list
a inserção no meio. Isso é verdade mesmo se você entender todos os contêineres e puder tomar uma decisão informada com base na complexidade algorítmica.Minha biblioteca 'aleatória' fornece um invólucro altamente conveniente em torno das classes aleatórias C ++ 11. Você pode fazer quase todas as coisas com um simples método 'get'.
Exemplos:
Número aleatório em um intervalo
Booleano aleatório
Valor aleatório de um std :: initilizer_list
Iterador aleatório do intervalo do iterador ou todo o contêiner
E ainda mais coisas! Confira a página do github:
https://github.com/effolkronium/random
fonte
I vermelho todo o material acima, cerca de 40 outras páginas com C ++ no-lo como este e assistiu ao vídeo do Stephan T. Lavavej "STL" e ainda não tinha certeza de como aleatório números obras na práxis por isso, tomei um domingo inteiro para descobrir do que se trata e como funciona e pode ser usado.
Na minha opinião, a STL está certa sobre "não usar mais o srand" e ele explicou bem no vídeo 2 . Ele também recomenda usar:
a)
void random_device_uniform()
- para geração criptografada, mas mais lenta (do meu exemplo)b) os exemplos com
mt19937
- mais rápido, capacidade de criar sementes, não criptografadasPeguei todos os livros c ++ 11 reivindicados aos quais tenho acesso e descobri que autores alemães como Breymann (2015) ainda usam um clone de
apenas em
<random>
vez de<time> and <cstdlib>
#includings - tenha cuidado para aprender apenas com um livro :).Significado - que não deve ser usado desde c ++ 11 porque:
Finalmente encontrei a melhor explicação de 20 livros nos livros mais recentes de Bjarne Stroustrups - e ele deve saber tudo - em "Um tour pelo C ++ 2019", "Princípios e práticas de programação usando C ++ 2016" e "Linguagem de programação C ++ 4ª edição 2014 "e também alguns exemplos em" Lippmans C ++ primer quinta edição 2012 ":
E é realmente simples, porque um gerador de números aleatórios consiste em duas partes: (1) um mecanismo que produz uma sequência de valores aleatórios ou pseudo-aleatórios. (2) uma distribuição que mapeia esses valores em uma distribuição matemática em um intervalo.
Apesar da opinião do cara da Microsofts STL, Bjarne Stroustrups escreve:
O
void die_roll()
exemplo é de Bjarne Stroustrups - boa ideia gerando mecanismo e distribuição comusing
(mais sobre isso aqui) .Para poder fazer uso prático dos geradores de números aleatórios fornecidos pela biblioteca padrão
<random>
aqui, alguns códigos executáveis com exemplos diferentes são reduzidos ao mínimo necessário, que esperamos ter tempo e dinheiro seguros para vocês:Eu acho que isso acrescenta tudo e, como eu disse, levei um monte de leitura e tempo para dedicar a esses exemplos - se você tiver mais informações sobre geração de números, fico feliz em saber sobre isso via pm ou na seção de comentários e irá adicioná-lo, se necessário, ou editar esta postagem. Bool
fonte
Aqui está algo que eu acabei de escrever nesse sentido:
~
fonte
Aqui está um recurso que você pode ler sobre o gerador de números pseudo-aleatórios.
https://en.wikipedia.org/wiki/Pseudorandom_number_generator
Basicamente, os números aleatórios no computador precisam de uma semente (esse número pode ser a hora atual do sistema).
Substituir
De
fonte
Você tem duas situações comuns. A primeira é que você deseja números aleatórios e não se preocupa com a qualidade ou a velocidade de execução. Nesse caso, use a seguinte macro
que fornece p no intervalo de 0 a 1 - epsilon (a menos que RAND_MAX seja maior que a precisão de um duplo, mas se preocupe com isso quando você o encontrar).
int x = (int) (uniforme () * N);
Agora fornece um número inteiro aleatório de 0 a N -1.
Se você precisar de outras distribuições, precisará transformar p. Ou, às vezes, é mais fácil chamar uniform () várias vezes.
Se você deseja um comportamento repetitivo, propague com uma constante, caso contrário, proponha uma chamada para time ().
Agora, se você se preocupa com a qualidade ou o desempenho em tempo de execução, reescreva uniform (). Mas, caso contrário, não toque no código. Mantenha sempre uniforme () em 0 a 1 menos epsilon. Agora você pode agrupar a biblioteca de números aleatórios C ++ para criar um uniforme melhor (), mas essa é uma espécie de opção de nível médio. Se você se preocupa com as características do RNG, também vale a pena investir um pouco de tempo para entender como os métodos subjacentes funcionam e fornecer um. Portanto, você tem controle total do código e pode garantir que, com a mesma semente, a sequência sempre será exatamente a mesma, independentemente da plataforma ou de qual versão do C ++ você está vinculando.
fonte