Сгенерировать случайное число в C

#random

#Случайный

Вопрос:

Я пытаюсь сгенерировать случайное число, но оно не должно быть определенным числом. Итак, я передаю функции число, которое не должно быть случайным числом, и диапазон, в котором оно должно быть сгенерировано, и я повторно вызываю функцию, если сгенерированное случайное число является числом, которое не должно генерироваться, так что это занимает много времени и приводит к завершению функции.моя программа. Я использую следующий код, дайте мне знать, насколько эффективно я могу сгенерировать случайное число, не дожидаясь долго или даже без повторного вызова функции.

здесь rank1 — это переданное ему число, которое не должно генерироваться, а size1 — это число, обозначающее диапазон максимально допустимого значения

 int rgenerator(int rank1, int size1)
{

    int iseed, k;
    time_t seconds;
    time(amp;seconds); 
    iseed=(unsigned int) seconds;

    srand(iseed);

    k=rand()%size1;

    if(k!=rank1)
        return k;
    else 
        rgenerator(rank1,size1);

}
 

Ответ №1:

Здесь применяется стандартное предостережение: вы хотите вызвать srand его ровно один раз во время инициализации и никогда не вызывать его снова.

Что касается отказа от генерации rank1 , я думаю, я бы просто уменьшил диапазон на 1, а затем, если результат, который вы получите, равен >= to rank1 , добавьте к нему единицу, чтобы создать «дыру» rank1 .

Ответ №2:

Несколько комментариев:

  1. Вам не нужно srand() делать это каждый раз. В любом случае, вы действительно не должны заполнять его более одного раза во время выполнения программы. Поместите это в начале вашего main() метода или создайте здесь статический флаг и введите его только один раз.
  2. Поскольку time() дает секунды, srand будет повторно вводить генератор в одно и то же состояние каждый раз, когда он вызывается в течение одной и той же секунды, что (особенно при такой рекурсии) может быть от тысяч до миллионов раз, возвращая одно и то же случайное число. Обратите внимание, что рекурсия приведет к переполнению стека (потенциально часть вашей проблемы) после ~ 5000 уровней рекурсии. Поэтому:
  3. Измените рекурсию на while цикл.
  4. Какой у вас размер rank1 и size1 каким он будет? Если, например size1 , равно RAND_MAX и rank1 равно нулю, все должно быть в порядке. Если, однако, size1 равно 1, а ранг 1 равен 0, вы никогда не сможете вернуться.

Это может быть лучшей реализацией:

 int rgenerator(int rank1, int size1) {
    // Prevent division by zero.
    assert(size1 > 0);

    // Prevent infinite loops from no valid returns
    assert(rank1 != 0 || size1 > 1);

    int randnum;
    do {
        randnum = rand() % size1;
    } while (randnum != rank1);

    return randnum;
}
 

Теперь прокомментируйте этот код:

  1. Есть более … краткие… способы написания этого цикла, но этот способ должен быть наиболее понятным.
  2. Вероятно, вам следует изменить утверждения, чтобы возвращать ноль, если вы их еще не изучили.
  3. Вы также можете создавать size1 - 1 числа и разделять их так, чтобы пропускать rank1 , но я оставлю этот код в качестве упражнения для читателя.

Комментарии:

1. Они останавливают программу там, если условие равно false. Очень полезно для отладки, но, как я уже сказал, на вашем уровне вы должны просто изменить assert(x) if(!(x)) return 0; или даже вернуть значение -1 и проверить это условие ошибки в коде, вызывающем этот метод.