Генерация случайных чисел на C ++ или Python - PullRequest
2 голосов
/ 02 марта 2012

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

1 Интересно, имеет ли это отношение к программе собственного Мерсенна-Твистера или других псевдослучайных подпрограмм, чтобы получить хороший генератор чисел,Кроме того, я не понимаю, почему я не должен доверять родным или библиотечным генераторам как random.uniform () в numpy, rand () в C ++.Я понимаю, что могу самостоятельно создавать генераторы для распределений, отличных от равномерного (обратная функция перераспределения метор, полярный метод).Но разве плохо использовать один встроенный генератор для равномерной выборки?

2 Что не так с начальным временем по умолчанию?Нужно ли заново и как часто в примере кода (и почему)?

3 Может быть, у вас есть хорошие ссылки на эти темы!

- редактировать Точнее, мне нужны случайные числадля многозадачных процедур оптимизации и для единообразной выборки пространства для инициализации некоторых других параметров процедуры оптимизации.Мне также нужны случайные числа для методов Монте-Карло (анализ чувствительности).Я надеюсь, что точность поможет определить суть вопроса.

Ответы [ 4 ]

5 голосов
/ 02 марта 2012

Ну, я не могу говорить о C ++, но Python использует Mersenne Twister . Так что нет необходимости реализовывать свои собственные в Python. Кроме того, Python использует системное время в качестве начального числа, если нет другого источника случайности; это системно-зависимая проблема. См. Также os.urandom документы об этом.

Интересно написать свой собственный. Псевдокод на странице MT Wikipedia понятен и прост в реализации.

Конечно, применяются обычные предостережения. Это не криптографический генератор случайных чисел. Не все перестановки в длинном списке могут быть сгенерированы random.shuffle, и так далее. Но для использования, которое вы укажете, вполне вероятно, что Mersenne Twister подойдет.

3 голосов
/ 02 марта 2012

В C ++ библиотека <random>, вероятно, предоставляет все, что вам нужно. Он имеет 3 различных алгоритма шаблонов PRNG, в том числе Mersenne Twister, 3 адаптера для использования, 9 конкретных генераторов случайных чисел, а также доступ к недетерминированному источнику случайных чисел вашей системы.

Кроме того, он имеет 20 распределений случайных чисел, которые включают равномерное, нормальное, бернуллиево-пуассоновское распределение и выборочное распределение.

Вот (слегка модифицированный) пример из C ++ 11 FAQ Страуструпа.

#include <iostream>
#include <random>
#include <string>
#include <vector>
#include <functional>

int main()
{
    auto rand = std::bind(
                    std::normal_distribution<>(15.0,4.0),
                    std::mt19937());

    std::vector<int> output(32);

    for (int i = 0; i<400; ++i)
        ++output[rand()];

    for (int i = 0; i<output.size(); ++i)
        std::cout << i << '\t' << std::string(output[i],'*') << '\n';
}

0
1
2       *
3       **
4       **
5       **
6       ***
7       ***
8       ******
9       ***************
10      **************************
11      ******************
12      ************************************************
13      ******************************************
14      ****************************************
15      *******************************
16      ***************************************
17      **************************************
18      *************************
19      *****************
20      ************
21      ************
22      *****
23      *******
24      ***
25      **
26
27      *
28
29
30
31
1 голос
/ 02 марта 2012

Python's random.uniform() в порядке. На самом деле он уже использует Mersenne-Twsiter .

Тем не менее, вам лучше избегать C и C ++ rand(), поскольку он часто выдает неверные случайные числа (см. Также Какие распространенные алгоритмы используются для C rand ()? ). Хуже того, в Windows RAND_MAX составляет всего 0x7fff , поэтому вы не можете получить более 32768 различных значений. Если вы могли бы использовать C ++ 11, проверьте новую библиотеку <random> , которая содержит много генераторов случайных чисел, включая MT-19937. В противном случае вы все равно можете использовать Boost.Random .


Хорошо заполнить генератор случайных чисел временем, если (1) вы не работаете с серьезной криптографией (в любом случае вы не должны использовать Mersenne-Twsiter в криптографии), и (2) Вы можете гарантировать, что невозможно получить два начальных числа с одинаковым значением времени, что приведет к генерации одинаковой последовательности.

1 голос
/ 02 марта 2012

По крайней мере, в C ++, rand иногда бывает довольно низкого качества, поэтому код должен редко использовать его для чего-либо, кроме таких вещей, как бросание костей или игра в карты в детских играх.В C ++ 11, однако, был добавлен набор классов генераторов случайных чисел хорошего качества, поэтому вы должны обычно использовать их по предпочтению.

Заполнение на основе time может работать нормально при некоторых обстоятельствах, но неесли вы хотите, чтобы кому-то другому было трудно дублировать одну и ту же серию чисел (например, если вы генерируете одноразовые номера для шифрования).Обычно вы хотите заполнить только один раз в начале программы, по крайней мере, в однопоточной программе.При многопоточности вам часто требуется отдельное начальное число для каждого потока, и в этом случае каждый из них должен начинаться с уникальности, чтобы не создавать одинаковые последовательности во всех потоках.

...