Em um aplicativo pequeno escrito em C / C ++, estou enfrentando um problema com a rand
função e talvez a semente:
Eu quero produzir uma sequência de números aleatórios que são de ordens diferentes, ou seja, com diferentes valores de logaritmo (base 2). Mas parece que todos os números produzidos são da mesma ordem, flutuando apenas entre 2 ^ 25 e 2 ^ 30.
É porque rand()
é semeado com o tempo do Unix, que agora é um número relativamente grande? O que estou esquecendo? Estou semeando rand()
apenas uma vez no início do main()
.
rand()
retornar números uniformemente distribuídos (a documentação com alta classificação no Google diz isso explicitamente), não acho que essa pergunta seja útil para futuros leitores. É por isso que não votar, mas não o desanime de usar o SO.Respostas:
Existem apenas 3% dos números entre 1 e 2 30 que NÃO estão entre 2 25 e 2 30 . Então, isso parece bastante normal :)
Porque 2 25 /2 30 = 2 -5 = 1/32 = 0,03125 = 3,125%
fonte
>>
deslocamento de bits - isso fornecerá números menores. (Ou tomar um módulo com%
.)0
- e se cada bit é aleatória ...O verde mais claro é a região entre 0 e 2 25 ; o verde mais escuro é a região entre 2 25 e 2 30 . Os ticks são potências de 2.
fonte
Você precisa ser mais preciso: deseja valores diferentes do logaritmo da base 2, mas que distribuição você deseja para isso? As funções padrão rand () geram uma distribuição uniforme; você precisará transformar essa saída usando a função quantil associada à distribuição que deseja.
Se você nos informar a distribuição, podemos informar a
quantile
função que você precisa.fonte
Se você deseja ordens de magnitude diferentes, por que não tentar
pow(2, rand())
? Ou talvez escolha o pedido diretamente como rand (), como Harold sugeriu?fonte
rand()
pode ir atéRAND_MAX
, você realmente precisa para dimensionar o número aleatório para que o resultado não transborde ...@ C4stor fez um grande ponto. Mas, para um caso mais geral e mais fácil de entender para humanos (base 10): para o intervalo de 1 a 10 ^ n, ~ 90% dos números são de 10 ^ (n-1) a 10 ^ n, portanto, ~ 99% dos números vão de 10 ^ (n-2) a 10 ^ n. Continue adicionando quantas casas decimais desejar.
Matemática engraçada, se você continuar fazendo isso por n, poderá ver que de 1 a 10 ^ n, 99.9999 ...% = 100% dos números são de 10 ^ 0 a 10 ^ n com esse método.
Agora, sobre o código, se você deseja um número aleatório com ordens aleatórias de magnitude, de 0 a 10 ^ n, você pode fazer:
Gere um pequeno número aleatório de 0 a n
Se você souber o intervalo que n possui, gere um grande número aleatório de ordem 10 ^ k, onde k> max {n}.
Corte o número aleatório mais longo para obter os n dígitos desse grande número aleatório.
fonte
A resposta básica (e correta) já foi dada e aceita acima: existem 10 números entre 0 e 9, 90 números entre 10 e 99, 900 entre 100 e 999, etc.
Para uma maneira computacionalmente eficiente de obter uma distribuição com distribuição aproximadamente logarítmica, você deseja deslocar seu número aleatório à direita por um número aleatório:
Não é perfeito, mas é muito mais rápido que a computação
pow(2, rand()*scalefactor)
. Será "irregular" no sentido de que a distribuição será uniforme para números dentro de um fator 2 (uniforme para 128 a 255, metade da densidade para 256 a 1023, etc.).Aqui está um histograma da frequência dos números de 0 a 31 (em 1 milhão de amostras):
fonte
rand()>>(rand()&31);
, seria de esperar intuitivamente 1/32 dos números com 32 bits, 1/32 dos números com 31 bits e 1/32 dos números com 30 bits etc. Mas isso é não os resultados que você está obtendo, apenas cerca de 1/64 dos números resultaria em 32 bits, enquanto quase metade deve ser 0. Como minha matemática mental discorda de suas medidas, terei que fazer minhas próprias medidas para descobrir isso.Há um número exatamente igual de números entre 0 e 2 ^ 29 e 2 ^ 29 e 2 ^ 30.
Outra maneira de analisar o problema: considere a representação binária do número aleatório gerado, a probabilidade de que o bit mais alto seja 1 é igual a 1/2 e, portanto, você recebe a ordem 29 pela metade. O que você deseja é ver um número que esteja abaixo de 2 ^ 25, mas isso significa que os 5 bits mais altos são todos zero, o que acontece com uma baixa probabilidade de 1/32. As chances são de que, mesmo que você o execute por um longo período, você nunca verá a ordem abaixo de 15 (a probabilidade é algo como rolar 6 6 vezes seguidas).
Agora, a parte da sua pergunta sobre a semente. Não, a semente não pode determinar o intervalo a partir do qual os números são gerados, apenas determina o primeiro elemento inicial. Pense em rand () como uma sequência de todos os números possíveis no intervalo (permutação predeterminada). A semente determina onde você começa a desenhar números da sequência. É por isso que se você deseja (pseudo) aleatoriedade, usa o tempo atual para inicializar a sequência: você não se importa que a posição de onde você começa não seja distribuída uniformemente, tudo o que importa é que você nunca comece da mesma posição.
fonte
usá-
pow(2,rand())
lo dará as respostas em ordem da magnitude desejada !!fonte
Se você deseja usar números aleatórios em um serviço online, pode usar o wget para isso, pode querer ver que também pode usar serviços como o random.org para sua geração de números aleatórios, pode capturá-los usando o wget e depois ler os números em o arquivo baixado
http://programmingconsole.blogspot.in/2013/11/a-better-and-different-way-to-generate.html
fonte