Как создать генератор случайных чисел безопасным и переносимым способом? - PullRequest
3 голосов
/ 28 февраля 2020

Фон:

Поскольку , рекомендуется использовать std::random_device вместо времени для заполнения генератора случайных чисел. Если мы посмотрим на связанную документацию , мы можем прочитать, что:

std::random_device может быть реализовано в терминах механизма реализации псевдослучайных чисел, определяемого реализацией если недетерминированный c источник (например, аппаратное устройство) недоступен для реализации . В этом случае каждый std::random_device объект может генерировать одну и ту же последовательность чисел .

выделение шахты

Давайте теперь рассмотрим следующий пример :

int main()
{
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution distr(0, 9);

    // Print a sequence of 10 uniformly distributed random integers
    for(std::size_t i = 0; i < 10; ++i)
        std::cout << distr(gen) << ' ';

    return 0;
}

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

В этом случае std::random_device намного хуже, чем заполнение генератора случайных чисел текущим временем:

std::mt199937 gen(std::chrono::high_resolution_clock::now().time_since_epoch().count()); // time seed

Проблема:

Меня беспокоит то, что если кто-то захочет написать программу, которая будет опираться на некоторые случайные числа и требует:

  1. Для переносимости
  2. Для гарантии отсутствия -deterministi c случайность

Тогда std::random_device не будет подходящей. С другой стороны, использование всегда затравки времени было бы довольно разочаровывающим «решением», поскольку, если бы у данной платформы был доступ к неопределенному c доступному источнику, std::random_device был бы тогда «более безопасным».

Вопрос:

Мой вопрос разделен на две части:

  1. Пользовательское пространство
    • Существует ли портативный способ проверки, если такой Определенный c источник доступен на текущей платформе?
  2. На стороне компилятора
    • Разрешено ли компилятору заменять std::random_device seed на начальные числа времени, если платформа хоста имеет нет недетерминированных c источник доступен? Или в стандарте есть что-то, что предотвратило бы такую ​​замену?
    • Если стандарт не запрещает такое поведение, что может быть причиной того, что компиляторы не будут его реализовывать?

Возможно, это должны быть 2 или 3 отдельных вопроса. Так как фон и проблема являются общими, я просил их в том же посте для целей полноты на topi c. Пожалуйста, дайте мне знать, если мне все равно придется разделить их на отдельные вопросы.

1 Ответ

2 голосов
/ 28 февраля 2020

Существует ли портативный способ проверить, доступен ли такой недетерминированный c источник на текущей платформе?

Вы можете использовать entropy функция-член std::random_device для проверки, является ли источник неопределенным c или нет. К сожалению, это не static constexpr функция, поэтому вам придется использовать обычный оператор if, такой как

int main()
{
    std::random_device rd;
    std::size_t seed;
    if (rd.entropy())
        seed = rd();
    else
        seed = std::chrono::high_resolution_clock::now().time_since_epoch().count();
    std::mt19937 gen(seed);
    std::uniform_int_distribution distr(0, 9);

    // Print a sequence of 10 uniformly distributed random integers
    for(std::size_t i = 0; i < 10; ++i)
        std::cout << distr(gen) << ' ';

    return 0;
}

. Разрешено ли компилятору заменять std::random_device seed на время seed, если платформа хоста имеет нет недетерминированного c источника в наличии? Или в стандарте есть что-то, что могло бы предотвратить такую ​​замену?

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...