Мой коллега и я вместе работаем над проектом в Монте-Карло на C ++. Она использует Visual Studio, я использую Xcode, мы делимся кодом через git.
Мы рассчитываем американские цены опционов благодаря данному методу, который требует генерации случайных чисел. Мы поняли, что получаем неправильные результаты для определенного параметра K (чем выше параметр, тем больше неправильный ответ), и мой коллега обнаружил, что изменение случайного источника для Mersenne Twister на rand () (хотя плохой генератор) делает результаты хорошими для всего диапазона К.
Но когда я изменил исходный код моей версии кода, он ничего не сделал.
Еще более загадочно для меня, я создал новый проект Xcode, скопировал в него весь ее источник, и он все еще дает мне неправильные результаты (пока она получает хорошие). Так что это не может происходить из самого кода.
Я очистил проект, перезапустил Xcode, даже перезапустил мой компьютер (…), но ничего не изменилось: наши проекты ведут себя согласованно, но по-разному, с тем же кодом.
(РЕДАКТИРОВАТЬ: по-разному, но последовательно, я не имею в виду, что мы не имеем одинаковую последовательность чисел. Я имею в виду, что ее оценка Монте-Карло сходится к 4. и мой к 3.)
Есть ли у вас какие-либо идеи о том, что может быть причиной такого двойного поведения?
Вот случайный код генерации:
double loiuniforme() //uniform law
{
return (double)((float)rand() / (float)RAND_MAX);
}vector<double> loinormale() //normal law
{
vector<double> loinormales(2, 0.);
double u1 = loiuniforme();
double v1 = loiuniforme();
loinormales[0] = sqrt(-2 * log(u1))*cos(2 * M_PI*v1);
loinormales[1] = sqrt(-2 * log(u1))*sin(2 * M_PI*v1);
return(loinormales);
}
РЕДАКТИРОВАТЬ: MT RNG, используемый ранее был:
double loiuniforme()
{
mt19937::result_type seed = clock();
auto real_rand = std::bind(std::uniform_real_distribution<double>(0,1), mt19937(seed));
return real_rand();
}
Стандарт C ++ не определяет, какой алгоритм используется rand()
, Кто бы ни написал компилятор, он может свободно использовать любую реализацию, какую захочет, и нет никакой гарантии, что он будет вести себя одинаково на двух разных компиляторах, на двух разных архитектурах или даже в двух разных версиях одного и того же компилятора.
Вы должны создать только один генератор и использовать его для каждого числа.
mt19937::result_type seed = clock();
а также
mt19937(seed)
создайте новый генератор с новым начальным числом каждый раз, когда вы вызываете функцию.
Это приводит к тому, что случайность искажается.
Вы можете использовать статические переменные в функции, так как они инициализируются при первом вызове:
double loiuniforme()
{
static std::mt19937 generator(clock());
static std::uniform_real_distribution<double> distribution(0, 1);
return distribution(generator);
}
(Когда вы сравниваете результаты со своим коллегой, используйте то же начальное число, чтобы убедиться, что вы получаете те же результаты.)
Вам нужно посеять rand
функция с одинаковым номером на обоих компьютерах. И даже тогда я не уверен, что базовый код на компьютерах и операционных системах будет возвращать одно и то же значение.
Что еще более важно, если вы хотите идентичные результаты, не используйте случайную функцию.