Eu preciso gerar números aleatórios dentro de um intervalo especificado, [max; min].
Além disso, os números aleatórios devem ser distribuídos uniformemente ao longo do intervalo, não localizados em um ponto específico.
Atualmente estou gerando como:
for(int i=0; i<6; i++)
{
DWORD random = rand()%(max-min+1) + min;
}
Em meus testes, números aleatórios são gerados em torno de apenas um ponto.
Example
min = 3604607;
max = 7654607;
Números aleatórios gerados:
3631594
3609293
3630000
3628441
3636376
3621404
Das respostas abaixo: OK, RAND_MAX é 32767. Estou na plataforma C ++ Windows. Existe algum outro método para gerar números aleatórios com uma distribuição uniforme?
rand()
era uniforme. Qual biblioteca você está usando?cstdlib.h
'srand()
não é uniforme: cplusplus.com/reference/cstdlib/randRespostas:
Porque
rand
é uma má ideiaA maioria das respostas que você obteve aqui faz uso da
rand
função e do operador de módulo. Esse método pode não gerar números uniformemente (depende do intervalo e do valor deRAND_MAX
) e, portanto, é desencorajado.C ++ 11 e geração em uma faixa
Com o C ++ 11, várias outras opções surgiram. Uma delas se adapta às suas necessidades, para gerar um número aleatório em um intervalo, muito bem:
std::uniform_int_distribution
. Aqui está um exemplo:E aqui está o exemplo de execução.
Outros geradores aleatórios
O
<random>
cabeçalho oferece inúmeros outros geradores de números aleatórios com diferentes tipos de distribuições, incluindo Bernoulli, Poisson e normal.Como posso embaralhar um contêiner?
O padrão fornece
std::shuffle
, que pode ser usado da seguinte forma:O algoritmo irá reordenar os elementos de forma aleatória, com uma complexidade linear.
Boost.Random
Outra alternativa, caso você não tenha acesso a um compilador C ++ 11 +, é usar Boost.Random . Sua interface é muito semelhante à do C ++ 11.
fonte
mt19937
tipo?1 9 6 2 8 7 1 4 7 7
,. Você sabe como randomizar isso toda vez que rodamos o programa?[editar] Aviso: Não use
rand()
para estatísticas, simulação, criptografia ou qualquer coisa séria.É bom o suficiente para fazer os números parecerem aleatórios para um humano típico com pressa, nada mais.
Veja a resposta de @Jfefrey para melhores opções, ou esta resposta para números aleatórios cripto-seguros.
Geralmente, os bits altos mostram uma distribuição melhor do que os bits baixos, portanto, a maneira recomendada de gerar números aleatórios de um intervalo para fins simples é:
Nota : certifique-se de que RAND_MAX + 1 não transborde (obrigado Demi)!
A divisão gera um número aleatório no intervalo [0, 1); "estique" isso para o intervalo necessário. Somente quando max-min + 1 se aproxima de RAND_MAX você precisa de uma função "BigRand ()" como postada por Mark Ransom.
Isso também evita alguns problemas de fatiamento devido ao módulo, o que pode piorar ainda mais seus números.
Não é garantido que o gerador de números aleatórios embutido tenha a qualidade necessária para simulações estatísticas. É normal que os números "pareçam aleatórios" para um humano, mas para uma aplicação séria, você deve pegar algo melhor - ou pelo menos verificar suas propriedades (distribuição uniforme geralmente é boa, mas os valores tendem a se correlacionar, e a sequência é determinística ) Knuth tem um tratado excelente (embora difícil de ler) sobre geradores de números aleatórios, e recentemente descobri que o LFSR é excelente e muito simples de implementar, já que suas propriedades são adequadas para você.
fonte
( rand() / ((double)RAND_MAX+1)) * (max-min+1) + min
simplesmente mova a conversão para o dobro e evite o problema.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
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 inspirouC++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 seuRandom
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:random_device
métodos específicos de sistema usa para oferta de semeadura de boa qualidadeA única pequena falha é que a oferta do módulo
random_device
não é apenas o cabeçalho, é necessário compilar e vincularboost_random
.Amostra mínima: um lançamento de dados
Embora a amostra mínima funcione bem, os programas reais devem usar um par de melhorias:
mt19937
umthread_local
: o gerador é bastante gordo (> 2 KB) e é melhor não alocado na pilhamt19937
com mais de um inteiro: o Mersenne Twister tem um grande estado e pode se beneficiar de mais entropia durante a inicializaçãoAlgumas 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á emstd::random_device
: o padrão não exige nenhuma qualidade mínima para sua produção (desde queentropy()
retorne0
) 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
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
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.A solução pior é melhor
Amostra mínima: um lançamento de dados
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
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.
fonte
randutils
biblioteca agora se chama PCG.Se
RAND_MAX
for 32767, você pode dobrar o número de bits facilmente.fonte
rand
chamada retornar0x1234
e a segunda0x5678
, você receberá0x12345678
. Esse é o único número que você pode começar com0x1234
, porque o próximo número sempre será0x5678
. Você obtém resultados de 32 bits, mas tem apenas 32.768 números possíveis.Se você puder, use Boost . Tive sorte com sua biblioteca aleatória .
uniform_int
deve fazer o que quiser.fonte
uniform_int
então. É muito fácil gerar uma saída imparcial; várias questões aqui demonstram o método.Se você está preocupado com a aleatoriedade e não com a velocidade, deve usar um método seguro de geração de números aleatórios. Existem várias maneiras de fazer isso ... A mais fácil é usar o Gerador de números aleatórios do OpenSSL .
Você também pode escrever seu próprio usando um algoritmo de criptografia (como AES ). Escolhendo uma semente e um IV e, em seguida, criptografando novamente a saída da função de criptografia continuamente. Usar o OpenSSL é mais fácil, mas menos varonil.
fonte
Você deve olhar
RAND_MAX
para o seu compilador / ambiente específico. Acho que você veria esses resultados se estivesserand()
produzindo um número aleatório de 16 bits. (você parece estar assumindo que será um número de 32 bits).Não posso prometer que essa é a resposta, mas por favor poste seu valor de
RAND_MAX
e um pouco mais de detalhes sobre seu ambiente.fonte
Verificar o que
RAND_MAX
está em seu sistema - suponho que sejam apenas 16 bits e seu alcance é muito grande para isso.Além disso, consulte esta discussão sobre: Como gerar números inteiros aleatórios em um intervalo desejado e as notas sobre o uso (ou não) da função C rand () .
fonte
Este não é o código, mas essa lógica pode ajudá-lo.
fonte
Se quiser que os números sejam distribuídos uniformemente ao longo do intervalo, você deve dividir o intervalo em várias seções iguais que representam o número de pontos de que você precisa. Em seguida, obtenha um número aleatório com um mínimo / máximo para cada seção.
Como outra observação, você provavelmente não deve usar,
rand()
pois não é muito bom para gerar números aleatórios. Não sei em que plataforma você está executando, mas provavelmente há uma função melhor que você pode chamarrandom()
.fonte
Isso deve fornecer uma distribuição uniforme ao longo do intervalo
[low, high)
sem usar flutuadores, desde que o intervalo geral seja menor que RAND_MAX.e para valores maiores que RAND_MAX você quer algo como
É basicamente assim que std :: uniform_int_distribution faz as coisas.
fonte
Por sua natureza, uma pequena amostra de números aleatórios não precisa ser distribuída uniformemente. Afinal, eles são aleatórios. Concordo que, se um gerador de números aleatórios está gerando números que parecem estar agrupados de maneira consistente, provavelmente há algo errado com ele.
Mas tenha em mente que a aleatoriedade não é necessariamente uniforme.
Edit: Eu adicionei "pequena amostra" para esclarecer.
fonte
A solução dada pelo homem 3 rand para um número entre 1 e 10 inclusive é:
No seu caso, seria:
Claro, isso não é aleatoriedade ou uniformidade perfeita, como algumas outras mensagens estão apontando, mas isso é suficiente para a maioria dos casos.
fonte
@Solução
((double) rand() / (RAND_MAX+1)) * (max-min+1) + min
Aviso : Não se esqueça, devido ao alongamento e possíveis erros de precisão (mesmo se RAND_MAX fosse grande o suficiente), você só poderá gerar "caixas" distribuídas uniformemente e nem todos os números em [min, max].
@Solution: Bigrand
Aviso : Observe que isso dobra os bits, mas ainda não será capaz de gerar todos os números em seu intervalo em geral, ou seja, não é necessariamente verdade que BigRand () irá gerar todos os números entre em seu intervalo.
Informações : Sua abordagem (módulo) é "boa", desde que o intervalo de rand () exceda o seu intervalo de intervalo e rand () seja "uniforme". O erro para no máximo os primeiros números máx. - mín. É 1 / (RAND_MAX +1).
Além disso, sugiro mudar para o novo pacote aleatório e em C ++ 11 também, que oferece melhores e mais variedades de implementações do que rand ().
fonte
Esta é a solução que encontrei:
Esta é uma solução de balde, conceitualmente semelhante às soluções que usam
rand() / RAND_MAX
para obter um intervalo de ponto flutuante entre 0-1 e, em seguida, arredondar para um balde. No entanto, ele usa matemática puramente inteira e aproveita as vantagens do piso de divisão inteira para arredondar o valor para o intervalo mais próximo.Faz algumas suposições. Primeiro, ele assume que
RAND_MAX * (max - min + 1)
sempre caberá dentro de umint32_t
. SeRAND_MAX
for 32767 e cálculos internos de 32 bits forem usados, o intervalo máximo que você pode ter é 32767. Se sua implementação tiver um RAND_MAX muito maior, você pode superar isso usando um número inteiro maior (comoint64_t
) para o cálculo. Em segundo lugar, seint64_t
for usado, masRAND_MAX
ainda for 32767, em intervalos maiores do queRAND_MAX
você começará a obter "buracos" nos números de saída possíveis. Este é provavelmente o maior problema com qualquer solução derivada do dimensionamentorand()
.Os testes em um grande número de iterações, no entanto, mostram que esse método é muito uniforme para intervalos pequenos. No entanto, é possível (e provável) que matematicamente isso tenha um pequeno viés e possivelmente desenvolva problemas quando o intervalo se aproxima
RAND_MAX
. Teste você mesmo e decida se ele atende às suas necessidades.fonte
Obviamente, o código a seguir não fornecerá números aleatórios, mas números pseudoaleatórios. Use o seguinte código
Por exemplo:
Você deve ligar
caso contrário, os números não serão quase aleatórios.
fonte
Acabei de encontrar isso na Internet. Isso deve funcionar:
fonte