RAND () генерирует одно и то же число – даже с srand(time(NULL)) в моем main!
Итак, я пытаюсь создать случайный вектор (подумайте о геометрии, а не о расширяемом массиве), и каждый раз, когда я вызываю свою функцию случайного вектора, я получаю одно и то же значение 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, тогда как другие числа, похоже, следуют (псевдо) случайности отлично. Однако, если я поставлю вызов, чтобы определить, скажем, Рэнди перед randx, Рэнди всегда вернется 8.
почему мое первое случайное число всегда 8? Я неправильно высеваю?
6 ответов
проблема в том, что генератор случайных чисел засевается значениями, которые очень близки друг к другу - каждый запуск программы изменяет только возвращаемое значение time() на небольшое количество - может быть, 1 секунду, может быть, даже нет! Довольно плохой стандартный генератор случайных чисел затем использует эти аналогичные начальные значения для генерации, по-видимому, идентичных начальных случайных чисел. В принципе, вам нужен лучший генератор начального семени, чем time () и лучший генератор случайных чисел, чем Ранд.)(
используемый алгоритм фактического цикла, я думаю, поднят с ускоренного C++ и предназначен для получения лучшего распространения чисел в требуемом диапазоне, чем, скажем, с помощью оператора mod. Но это не может компенсировать то, что всегда (эффективно) дается одно и то же семя.
Я не вижу никаких проблем с вашим 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;
кроме того, вы можете даже избавиться от этого странного bucket_size
переменная и используйте следующий метод для генерации чисел от a
to 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;
простое 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.
У меня была точно такая же проблема. Я исправил это, переместив вызов srand (), чтобы он был вызван только один раз в моей программе (ранее я заполнял его в верхней части вызова функции). Не совсем понимаю технические детали - но проблема была решена.
ваша реализация через целочисленное деление игнорирует наименьший 4-5 бит случайного числа. Поскольку ваш RNG засеян системным временем, первое значение, которое вы получите из него, будет меняться только (в среднем) каждые 20 секунд.
Это должно работать:
randx = (min) + (int) ((max - min) * rand() / (RAND_MAX + 1.0));
здесь
rand() / (RAND_MAX + 1.0)
является случайным двойным значением в [0, 1), а остальное просто сдвигает его.