Números aleatórios em C ++

12

Recentemente, me acostumei a idiomas modernos, que incluem um bom gerador aleatório de ações, que geralmente é o Mersenne Twister; agora que voltei ao C ++, tenho que decidir o que usar.

Eu procurei pelas implementações do Mersenne Twister e notei que são muitas: existe uma que é mais usada e difundida, ou devo escolher uma assumindo que todas são igualmente boas?

o0 '.
fonte
1
Eu gosto da sua separação de C ++ e linguagens modernas.
Jcora # 17/12
2
Talvez dizer "nível superior" fosse mais apropriado.
o0 '.
Eu acho que esta pergunta pertence ao stackoverflow
TravisG 18/03/2012
5
No SO, eu daria uma resposta diferente, porque não saberia que era para um mecanismo de jogo, em vez de, digamos, simulações de Monte Carlo para terapias médicas, caso em que não ter 624 dimensões de aleatoriedade pode ser mortal.

Respostas:

19

O C ++ 11 inclui um gerador Mersenne Twister por padrão como parte de sua nova <random>interface. Por exemplo, para gerar números inteiros uniformemente entre [-10, 10] usando MT:

std::mt19937 eng; // This is the Mersenne Twister
std:::uniform_int_distribution<int> dist(-10, 10)
for (int i = 0; i < 10; ++i)
    std::cout << dist(eng) << std::endl;

A maior parte disso também está disponível em qualquer compilador que oferece TR1, embora os nomes sejam ligeiramente diferentes; std::tr1::mt19937e std::tr1::uniform_int<int>.

Normalmente, aconselho as pessoas a não usarem o Mersenne Twister. É um algoritmo correto, mas grande parte de sua popularidade é apenas marketing. 624 dimensões de aleatoriedade são mais do que a maioria das pessoas precisa, e o MT carrega requisitos de estado relativamente pesados ​​e, quando faz um recálculo de uma tabela completa, pode danificar o cache. Pessoalmente, sou parcial com o xorshift, que oferece excelentes períodos e distribuições razoáveis ​​para qualquer coisa que um jogo precise, com poucos requisitos de memória e CPU.

Eu escrevi um gerador xorshift compatível com C ++ 11 ( xorshift.hpp , xorshift.cpp ) e o coloquei em domínio público. Você pode conectar isso a qualquer função de randomização C ++ 11, como acima:

xorshift eng;
std:::uniform_int_distribution<int> dist(-10, 10)
for (int i = 0; i < 10; ++i)
    std::cout << dist(eng) << std::endl;

fonte
5
Sim, esse é o tipo de resposta que eu estava procurando, por isso eu postei aqui no gamedev:)
o0 '.
1
Só queria observar que nada nos arquivos vinculados indica que eles são de domínio público. Da maneira como a lei de direitos autorais funciona, é necessário que haja realmente uma observação clara, pois a lei assume "todas as reservas de direitos" por padrão. Na verdade, é ainda mais seguro usar algo como a licença de cláusula 2 do MIT ou BSD, já que algumas jurisdições basicamente não reconhecem "isso é de domínio público" como juridicamente vinculativo. Se você estiver interessado em ver as pessoas usarem seu código, talvez valha a pena cuidar disso.
Sean Middleditch
1
@seanmiddleditch: Estou sendo claro sobre isso aqui. Se você quiser com uma licença no estilo MIT, seguirei o exemplo do SQLite e o entregarei por apenas US $ 1000.
A falta de um cabeçalho no código que declara algo (o que o SQLite faz, iirc) é o principal problema. Se você não se importa, isso é legal. Estava apenas dando uma sugestão amigável.
21412 Sean Middleditch
1

Outro RNG que eu usei antes para fins de jogos é o "pequeno" RNG de Bob Jenkins, descrito aqui .

(Ele também tem um RNG de força criptográfica chamado ISAAC, mas é maior e mais lento, e os jogos não precisam desse nível de força.)

Nathan Reed
fonte
1
Isso parece mais caro que o xorshift (4 xors e 3 turnos vs. 4 adicionamentos, 6 turnos, 2 ors e um xor), tem um período pior e corre o risco de ciclos muito curtos com determinadas inicializações. Parece rápido, mas não mais rápido; período certo, mas nem perto do ideal; mesmas qualidades básicas de distribuição que o xorshift; Não vejo motivo para usá-lo.
Justo. Não sei o suficiente sobre a análise RNG para analisar as propriedades de distribuição e ciclo.
Nathan Reed