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), а остальное просто сдвигает его.