Получение одинакового набора случайных чисел при каждом запуске (с использованием как int, так и реального равномерного распределения) - PullRequest
0 голосов
/ 16 мая 2019

При каждом запуске генерируется одинаковый набор чисел. Я не уверен, почему это происходит. Есть ли другой способ генерации случайных чисел с использованием случайной библиотеки, которая предотвращает эту ошибку? или что-то не так с моим компилятором или программой?

Необходимо ли объявлять std :: default_random_engine как статический? потому что когда он не объявлен как статический, вы будете получать одно и то же число на каждой итерации. что является причиной этого?

#include <iostream>
#include <random>

float get_random() {
    static std::default_random_engine random;
    std::uniform_real_distribution<> distribution{0, 1};

    return distribution(random);
}

int main() {
    for (size_t i = 0; i < 10; i++) {
        std::cout<<get_random()<<std::endl;
    }

    return 0;
}

Ответы [ 2 ]

0 голосов
/ 17 мая 2019

Возьмите шесть листов бумаги и напишите на них цифры 1 - 6. Положите их в сумку и перемешайте. Теперь вылейте их из сумки и разложите на столе случайным образом.

Что говорит первый? Возможно 3! Хороший случайный результат! Отлично.

Что говорит второй? Возможно 5! Круто, тоже кажется довольно случайным.

Что говорит третий? Возможно 2! Сладкое.


Теперь, если вам нужно только три случайных числа, тогда все готово.

Что тебе в следующий раз понадобится три случайных числа?

Есть ли у вас:

  1. Снова посмотрите на первые три листа бумаги на вашем столе, или
  2. Положите кусочки бумаги обратно в пакет и перетасуйте их?

Второй, конечно! В противном случае вы получите те же результаты.


PRNG являются детерминированными . Они не совсем случайные. Они просто кормят вас своего рода заранее определенной последовательностью, по порядку. Сама последовательность выглядит как случайность, но для заданного начального числа фактический выбор последовательности уже сделан системой, когда вы сконструировали генератор.

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

Способ использования PRNG состоит в том, чтобы создать один генератор, а затем продолжать спрашивать его о следующем «случайном» числе в последовательности. Вот почему вы делаете этот объект static: так, чтобы он был создан один раз и повторно использован при последующих вызовах функции.

0 голосов
/ 16 мая 2019

std::default_random_engine - генератор псевдослучайных чисел, а PRNG - это просто алгоритмы, выходные данные которых напоминают случайные числа, но на самом деле не случайные. Они выполняют определенную операцию для некоторого внутреннего состояния и выводят следующее число на основе этого состояния, обеспечивая предсказуемую последовательность. Если вам нужна отдельная последовательность при каждом запуске с использованием PRNG, вам нужно «посеять» ее по-разному (т.е. инициализировать внутреннее состояние с другим значением).

В качестве альтернативы вы можете использовать вместо генератора реальных случайных чисел, который в C ++ задается как std::random_device, если он реализован. Если std::random_device::entropy() > 0, вы можете использовать его вместо std::default_random_engine для получения недетерминированных результатов.

Он также может использоваться для заполнения PRNG, если он недетерминированный:

#include <chrono>

uint32_t generate_seed() {
    // The most portable way to generate non-deterministic number
    // is via std::random_device, provided entropy is > 0.
    {
        std::random_device rd;
        if(rd.entropy() > 0.0) {
            return rd();
        }
    }

    // Random device is deterministic, you need some other
    // platform specific entropy source.
    // Good alternatives are:
    //  - /dev/urandom, on Linux;
    //  - BCryptGenRandom() function, on Windows;
    //  - RDRAND or RDSEED instruction, on
    //    recent enough Intel processors.
    // Bad alternatives are:
    //  - time() function, which is predictable if
    //    you know when the program was executed,
    //    and is repeatead if you run the program
    //    more than once per second.
    //  - std::chrono::high_resolution_clock::now(), which
    //    is a little better than time() because it
    //    changes faster, thus is less likely to be repeated.
    return std::chrono::high_resolution_clock::now()
        .time_since_epoch().count();
}

float get_random() {
    static std::default_random_engine random{generate_seed()};
    std::uniform_real_distribution<> distribution{0, 1};

    return distribution(random);
}
...