Gostaria de complementar as excelentes respostas de Angry Shoe e Peterchen com uma breve visão geral do estado da arte em 2015:
Algumas boas escolhas
randutils
A randutils
biblioteca (apresentação) é uma novidade interessante, oferecendo uma interface simples e recursos aleatórios (declarados) robustos. Tem a desvantagem de adicionar uma dependência ao seu projeto e, sendo novo, não foi exaustivamente testado. De qualquer forma, por ser gratuito (licença MIT) e somente cabeçalho, acho que vale a pena tentar.
Amostra mínima: um lançamento de dados
#include <iostream>
#include "randutils.hpp"
int main() {
randutils::mt19937_rng rng;
std::cout << rng.uniform(1,6) << "\n";
}
Mesmo se alguém não estiver interessado na biblioteca, o site ( http://www.pcg-random.org/ ) oferece muitos artigos interessantes sobre o tema da geração de números aleatórios em geral e a biblioteca C ++ em particular.
Boost.Random
Boost.Random
(documentação) é a biblioteca que inspirou C++11
's <random>
, com quem compartilha muito da interface. Embora teoricamente também seja uma dependência externa, Boost
agora tem um status de biblioteca "quase padrão" e seu Random
módulo pode ser considerado a escolha clássica para geração de números aleatórios de boa qualidade. Apresenta duas vantagens em relação à C++11
solução:
- é mais portátil, precisando apenas de suporte de compilador para C ++ 03
- seus
random_device
métodos específicos de sistema usa para oferta de semeadura de boa qualidade
A única pequena falha é que a oferta do módulo random_device
não é apenas o cabeçalho, é necessário compilar e vincular boost_random
.
Amostra mínima: um lançamento de dados
#include <iostream>
#include <boost/random.hpp>
#include <boost/nondet_random.hpp>
int main() {
boost::random::random_device rand_dev;
boost::random::mt19937 generator(rand_dev());
boost::random::uniform_int_distribution<> distr(1, 6);
std::cout << distr(generator) << '\n';
}
Embora a amostra mínima funcione bem, os programas reais devem usar um par de melhorias:
- faça
mt19937
umthread_local
: o gerador é bastante gordo (> 2 KB) e é melhor não alocado na pilha
- semente
mt19937
com mais de um inteiro: o Mersenne Twister tem um grande estado e pode se beneficiar de mais entropia durante a inicialização
Algumas escolhas não tão boas
A biblioteca C ++ 11
Embora seja a solução mais idiomática, a <random>
biblioteca não oferece muito em troca da complexidade de sua interface, mesmo para as necessidades básicas. A falha está em std::random_device
: o padrão não exige nenhuma qualidade mínima para sua produção (desde que entropy()
retorne 0
) e, a partir de 2015, MinGW (não o compilador mais usado, mas dificilmente uma escolha esotérica) sempre imprimirá 4
na amostra mínima.
Amostra mínima: um lançamento de dados
#include <iostream>
#include <random>
int main() {
std::random_device rand_dev;
std::mt19937 generator(rand_dev());
std::uniform_int_distribution<int> distr(1, 6);
std::cout << distr(generator) << '\n';
}
Se a implementação não estiver podre, esta solução deve ser equivalente à do Boost, e as mesmas sugestões se aplicam.
Solução de Godot
Amostra mínima: um lançamento de dados
#include <iostream>
#include <random>
int main() {
std::cout << std::randint(1,6);
}
Esta é uma solução simples, eficaz e organizada. Só defeito, vai demorar um pouco para compilar - cerca de dois anos, desde que o C ++ 17 seja lançado no prazo e a randint
função experimental seja aprovada no novo Padrão. Talvez nessa altura também as garantias sobre a qualidade da sementeira melhorem.
Amostra mínima: um lançamento de dados
#include <cstdlib>
#include <ctime>
#include <iostream>
int main() {
std::srand(std::time(nullptr));
std::cout << (std::rand() % 6 + 1);
}
A antiga solução C é considerada prejudicial, e por boas razões (veja as outras respostas aqui ou esta análise detalhada ). Ainda assim, tem suas vantagens: é simples, portátil, rápido e honesto, no sentido de que se sabe que os números aleatórios que se obtém dificilmente são decentes e, portanto, não se fica tentado a usá-los para fins sérios.
A solução de troll de contabilidade
Amostra mínima: um lançamento de dados
#include <iostream>
int main() {
std::cout << 9; // http://dilbert.com/strip/2001-10-25
}
Embora 9 seja um resultado um tanto incomum para um lançamento de dados regular, deve-se admirar a excelente combinação de boas qualidades nesta solução, que consegue ser a mais rápida, simples, amigável de cache e mais portátil. Ao substituir 9 por 4, obtém-se um gerador perfeito para qualquer tipo de dado de Dungeons and Dragons, enquanto ainda evita os valores carregados de símbolos 1, 2 e 3. A única pequena falha é que, por causa do mau humor dos trolls contadores de Dilbert, este programa realmente gera um comportamento indefinido.