#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:
Несколько комментариев:
- Вам не нужно
srand()
делать это каждый раз. В любом случае, вы действительно не должны заполнять его более одного раза во время выполнения программы. Поместите это в начале вашегоmain()
метода или создайте здесь статический флаг и введите его только один раз. - Поскольку
time()
дает секунды,srand
будет повторно вводить генератор в одно и то же состояние каждый раз, когда он вызывается в течение одной и той же секунды, что (особенно при такой рекурсии) может быть от тысяч до миллионов раз, возвращая одно и то же случайное число. Обратите внимание, что рекурсия приведет к переполнению стека (потенциально часть вашей проблемы) после ~ 5000 уровней рекурсии. Поэтому: - Измените рекурсию на
while
цикл. - Какой у вас размер
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;
}
Теперь прокомментируйте этот код:
- Есть более … краткие… способы написания этого цикла, но этот способ должен быть наиболее понятным.
- Вероятно, вам следует изменить утверждения, чтобы возвращать ноль, если вы их еще не изучили.
- Вы также можете создавать
size1 - 1
числа и разделять их так, чтобы пропускатьrank1
, но я оставлю этот код в качестве упражнения для читателя.
Комментарии:
1. Они останавливают программу там, если условие равно false. Очень полезно для отладки, но, как я уже сказал, на вашем уровне вы должны просто изменить
assert(x)
if(!(x)) return 0;
или даже вернуть значение -1 и проверить это условие ошибки в коде, вызывающем этот метод.