Rand() генерирует такое же число - даже с srand (time (NULL)) в моем главном!
Итак, я пытаюсь создать случайный вектор (думаю, геометрия, а не расширяемый массив), и каждый раз, когда я вызываю свою случайную векторную функцию, я получаю одно и то же значение x, хотя значения y и z разные.
int main () {
srand ( (unsigned)time(NULL));
Vector<double> a;
a.randvec();
cout << a << endl;
return 0;
}
используя функцию
//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;
}
По какой-то причине randx будет последовательно возвращать 8, тогда как другие числа, похоже, отлично следуют (псевдо) случайности. Однако, если я поставил вызов, чтобы определить, скажем, randy перед randx, randy всегда будет возвращать 8.
Почему мое первое случайное число всегда 8? Исправлен ли я неправильно?
Ответы
Ответ 1
Проблема заключается в том, что генератор случайных чисел высевается со значениями, которые очень близки друг к другу - каждый запуск программы меняет возвращаемое значение времени() на небольшую величину - может быть, на 1 секунду, а может быть даже на одну! Довольно плохой стандартный генератор случайных чисел затем использует эти одинаковые начальные значения для генерации, по-видимому, идентичных начальных случайных чисел. В принципе, вам нужен лучший начальный генератор семян, чем time() и лучший генератор случайных чисел, чем rand().
Используемый фактический алгоритм цикла, я думаю, снят с Accelerated С++ и предназначен для получения лучшего разброса чисел в требуемом диапазоне, чем скажем, используя оператор mod. Но он не может компенсировать всегда (эффективно) отдавать одно и то же семя.
Ответ 2
Я не вижу проблем с вашим srand()
, и когда я пытался использовать очень похожий код, я не получал один и тот же номер с первым rand()
. Однако я заметил еще одну возможную проблему.
do randx = (rand()/bucket_size)+min;
while (randx <= min && randx >= max);
Эта строка, вероятно, не делает то, что вы намеревались. Пока min < max
(и это всегда должно быть), невозможно, чтобы randx
было меньше или равно min
и больше или равно max
. Кроме того, вам вообще не нужно зацикливаться. Вместо этого вы можете получить значение между min и max, используя:
randx = rand() % (max - min) + min;
Ответ 3
Кроме того, вы можете даже избавиться от этой странной переменной bucket_size
и использовать следующий метод для генерации чисел от a
до b
включительно:
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;
Ответ 4
Простым quickfix является вызов rand
несколько раз после посева.
int main ()
{
srand ( (unsigned)time(NULL));
rand(); rand(); rand();
Vector<double> a;
a.randvec();
cout << a << endl;
return 0;
}
Чтобы лучше объяснить, первый вызов rand() в четырех последовательных прогонах тестовой программы дал следующий результат:
27592
27595
27598
27602
Обратите внимание, насколько они похожи? Например, если вы разделите rand()
на 100, вы получите то же число 3 раза подряд. Теперь рассмотрим второй результат rand() в четырех последовательных прогонах:
11520
22268
248
10997
Это выглядит намного лучше, не так ли? Я действительно не вижу причин для downvotes.
Ответ 5
У меня была такая же проблема. Я исправил его, переместив вызов srand(), поэтому он был вызван только один раз в моей программе (ранее я посеял его в верхней части вызова функции).
Не совсем понимаю технику, но проблема была решена.
Ответ 6
Ваша реализация посредством целочисленного деления игнорирует наименьший 4-5 бит случайного числа. Поскольку ваш RNG засевается системным временем, первое значение, которое вы получите от него, будет меняться только (в среднем) каждые 20 секунд.
Это должно работать:
randx = (min) + (int) ((max - min) * rand() / (RAND_MAX + 1.0));
где
rand() / (RAND_MAX + 1.0)
- случайное двойное значение в [0, 1), а остальное просто смещает его.
Ответ 7
Не имеет прямого отношения к коду в этом вопросе, но у меня была такая же проблема с использованием srand ((unsigned)time(NULL))
и по-прежнему с той же последовательностью значений, возвращаемых из следующих вызовов в rand()
.
Оказалось, что srand необходимо вызвать каждый поток, который вы используете его отдельно. У меня была загрузочная нить, которая генерировала случайный контент (это не было случайным вопросом о семенной проблеме). Я просто использовал srand в основном потоке, а не в загружаемом потоке. Таким образом, добавлено другое srand ((unsigned)time(NULL))
чтобы начать загрузку потока, исправил эту проблему.