Лучший способ получить случайное число по «индексу» из семени? - PullRequest
1 голос
/ 06 апреля 2020

Я хотел узнать хороший способ получить случайное число из индекса. В основном, вот пример того, что я хочу.

Из того, что я знаю о том, как std::rand() / rand() работает, он просто дает вам случайное число каждый раз, когда он вызывается, и каждый раз, когда вы сбрасываете seed, вызывая std :: srand, он выдает одинаковые точные числа. Но то, как работает rand, кажется очень глобальным, и это означает, что каждый раз, когда вы его называете, число изменяется на некоторый индекс, равный единице исходного числа (хотя я знаю, что это не совсем так, как работает под капотом)

// User manually provides a seed, not by std::time(nullptr)
get_random(3); // Return 1641
get_random(67); // returns 2782
get_random(5); // return 9832
get_random(67); // return 2782

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

int Class::get_random(int index) {
    std::srand(user_provided_seed); // reset the seed
    for (int i = 0; i < index; i++) {
        std::rand();
    }
    return std::rand();
}

Вышеприведенное работает отлично, в основном оно просто ожидает случайное число в качестве индекса и работает с этим числом, но я чувствую, что Приведенное выше выполняет слишком много работы, в моей программе я действительно ожидаю, что пользователь передаст довольно большой индекс, около 1000 с, и мне кажется, что простой вызов std :: rand () 1000 раз тратит впустую процессорное время.

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

Ответы [ 3 ]

1 голос
/ 06 апреля 2020

Есть несколько способов. Во-первых, как сказал @Peter в хранилище комментариев случайные значения (работает, если никто не использует std::rand или вы можете создать свой собственный std::random_engine).

Class {
    ...
    std::vector<int> values;
    std::mersenne_twister_engine engine;
}
int Class::get_random(int index) {
    for (int i = values.size(); i <= index; i++) {
        values.push_back(engine());
    }
    return values[index];
}

Или вы можете использовать псевдослучайную функцию, которую можно посчитать для Индекс отдельно. Например (в псевдокоде, потому что afaik в стандартной библиотеке нет ша):

int get_random(int index) {
    return (int)(sha256(str(seed) +  str(index));
}
0 голосов
/ 06 апреля 2020

Ваш подход в get_random - лучшее, что вы можете сделать.

Стандарт C требует rand для вывода той же последовательности чисел для данного семени. Однако, даже если задано начальное число, стандарт C точно не определяет, что это за последовательность. В частности:

См. Также этот вопрос .

0 голосов
/ 06 апреля 2020

Если rand () рекурсивный, другого пути быть не может. В этом случае каждое следующее число в случайной последовательности вычисляется на основе предыдущего и, следовательно, rand () должен выполняться каждый раз. Я не уверен, что rand () рекурсивен - вы можете изучить эту возможность, прежде чем беспокоиться о лучшем решении.

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