Rand () gerando o mesmo número - mesmo com Srand (tempo (nulo)) no meu principal!

StackOverflow https://stackoverflow.com/questions/3032726

  •  27-09-2019
  •  | 
  •  

Pergunta

Então, estou tentando criar um vetor aleatório (pense em geometria, não uma matriz expansível), e toda vez que chamo minha função de vetor aleatório, recebo o mesmo valor X, embora Y e Z sejam diferentes.

int main () {
    srand ( (unsigned)time(NULL));
    Vector<double> a;
    a.randvec();
    cout << a << endl;
    return 0;
}

usando a função

//random Vector
template <class T>
void Vector<T>::randvec()
{
    const int min=-10, max=10;
    int randx, randy, randz;

    const int bucket_size = RAND_MAX/(max-min);

    do randx = (rand()/bucket_size)+min;
    while (randx <= min && randx >= max);
    x = randx;

    do randy = (rand()/bucket_size)+min;
    while (randy <= min && randy >= max);
    y = randy;

    do randz = (rand()/bucket_size)+min;
    while (randz <= min && randz >= max);
    z = randz;
}

Por alguma razão, Randx retornará consistentemente 8, enquanto os outros números parecem estar seguindo perfeitamente a aleatoriedade (pseudo). No entanto, se eu fizer a ligação para definir, digamos, Randy antes de Randx, Randy sempre retornará 8.

Por que meu primeiro número aleatório é sempre 8? Estou semeando incorretamente?

Foi útil?

Solução

A questão é que o gerador de números aleatórios está sendo semeado com valores muito próximos - cada execução do programa altera apenas o valor de retorno do tempo () em uma pequena quantidade - talvez 1 segundo, talvez até nenhum! O gerador de números aleatórios padrão bastante ruim usa esses valores de sementes semelhantes para gerar números aleatórios iniciais aparentemente idênticos. Basicamente, você precisa de um melhor gerador de sementes iniciais do que o tempo () e um gerador de números aleatórios melhor do que o rand ().

O algoritmo de looping real usado é levantado do C ++ acelerado e destina -se a produzir uma melhor disseminação de números no intervalo necessário do que o uso do operador de mod. Mas não pode compensar sempre ser (efetivamente), dada a mesma semente.

Outras dicas

Eu não vejo nenhum problema com o seu srand(), e quando tentei executar um código extremamente semelhante, não recebi o mesmo número com o primeiro rand(). No entanto, notei outra questão possível.

do randx = (rand()/bucket_size)+min;
while (randx <= min && randx >= max);

Essa linha provavelmente não faz o que você pretendia. Enquanto min < max (e sempre deveria ser), é impossível para randx ser menor ou igual a min e maior ou igual a max. Além disso, você não precisa fazer um loop. Em vez disso, você pode obter um valor entre Min e Max usando:

randx = rand() % (max - min) + min;

Também para mencionar, você pode até se livrar dessa estranha bucket_size variável e use o seguinte método Para gerar números de a para b inclusivamente:

srand ((unsigned)time(NULL));

const int a = -1;
const int b = 1;

int x = rand() % ((b - a) + 1) + a;
int y = rand() % ((b - a) + 1) + a;
int z = rand() % ((b - a) + 1) + a;

Um simples quickfix é ligar rand algumas vezes depois de semear.

int main ()
{
    srand ( (unsigned)time(NULL));
    rand(); rand(); rand();

    Vector<double> a;
    a.randvec();
    cout << a << endl;
    return 0;
}

Apenas para explicar melhor, a primeira chamada para RAND () em quatro corridas seqüenciais de um programa de teste deu a seguinte saída:

27592
27595
27598
27602

Observe como eles são semelhantes? Por exemplo, se você dividir rand() Por 100, você receberá o mesmo número 3 vezes seguidas. Agora dê uma olhada no segundo resultado de rand () em quatro execuções sequenciais:

11520
22268
248
10997

Isso parece muito melhor, não é? Eu realmente não vejo nenhum motivo para os votos.

Eu tive o mesmo problema exatamente. Eu o corrigi movendo a chamada srand () para que ela fosse chamada apenas uma vez no meu programa (anteriormente eu a estava semeando na parte superior de uma chamada de função). Realmente não entendo os técnicos - mas foi resolvido o problema.

Sua implementação, através da divisão inteira, ignora o menor 4-5 bit do número aleatório. Como o seu RNG é semeado com o tempo do sistema, o primeiro valor que você obtém é alterado apenas (em média) a cada 20 segundos.

Isso deve funcionar:

randx = (min) + (int) ((max - min) * rand() / (RAND_MAX + 1.0));

Onde

rand() / (RAND_MAX + 1.0)

é um valor duplo aleatório em [0, 1) e o restante está apenas mudando.

Não está diretamente relacionado ao código nesta questão, mas tive o mesmo problema de usarsrand ((unsigned)time(NULL)) e ainda ter a mesma sequência de valores sendo retornados de seguintes chamadas para rand().

Aconteceu que o Srand precisa chamar em cada thread que você o está usando separadamente. Eu tinha um encadeamento de carregamento que estava gerando conteúdo aleatório (que não era aleatório porque o problema de sementes). Eu tinha acabado de usar o srand no encadeamento principal e não o encadeamento de carregamento. Então adicionou outro srand ((unsigned)time(NULL)) Para começar o encadeamento de carregamento, corrigiu esse problema.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top