Этот вопрос двоякий. Я перевожу R-скрипт на C ++, который использует комбинированный многорекурсивный генератор L'Ecuyer (CMRG) в качестве своего движка (в частности, MRG32k3a), который затем возвращает случайное число из равномерного распределения за интервал (0, 1). Минимальный пример в R показан ниже:
seednum<-100 # set seed
set.seed(seednum, kind="L'Ecuyer-CMRG") # set RNG engine
runif(1) # set distribution
Я хочу иметь возможность проверить мои результаты между сценарием R и кодом C ++ (поскольку сгенерированные случайные числа являются только началом). Я обнаружил, что PRNG с одинаковыми начальными числами на разных языках не обязательно дают один и тот же результат (так как они могут иметь параметры, которые компилятор может свободно указывать), как видно из сообщений SO * здесь и здесь . То есть использование одного и того же начального числа, одного и того же механизма и одного и того же распределения может привести к различным случайным числам в зависимости от конкретной реализации PRNG. Соответствующий пример между R и C ++ 11 приведен ниже. Используя вездесущий PRNG Мерсенна-Твистера в R:
seednum<-100
set.seed(seednum, kind="Mersenne-Twister")
runif(1)
В результате получается случайное число 0.3077661
. Делаем то же самое в C ++ 11:
#include <iostream>
#include <random>
int main()
{
unsigned seed = 100;
std::mt19937 generator (seed);
std::uniform_real_distribution<double> distribution (0.0, 1.0);
std::cout << distribution(generator) << std::endl;
return 0;
}
В результате получается случайное число 0.671156
. Первоначально я был смущен этим результатом, но предыдущие вопросы SO прояснили это для меня (как указано выше). Казалось бы, есть параметры, передаваемые в MRG32k3a в R, которые мне нужно реплицировать в C ++, чтобы генерировать те же случайные числа. Таким образом, первый вопрос: где я могу найти документацию по реализации MRG32k3a в R, в которой указаны эти параметры?
Второй вопрос касается реализации этого генератора в C ++ 11. Этот генератор не отображается в списке предварительно сконфигурированных типов движков в библиотеке <random>
C ++ 11, указанной здесь здесь . Пример реализации MRG32k3a в C можно найти здесь и показан ниже:
/*
32-bits Random number generator U(0,1): MRG32k3a
Author: Pierre L'Ecuyer,
Source: Good Parameter Sets for Combined Multiple Recursive Random
Number Generators,
Shorter version in Operations Research,
47, 1 (1999), 159--164.
---------------------------------------------------------
*/
#include <stdio.h>
#define norm 2.328306549295728e-10
#define m1 4294967087.0
#define m2 4294944443.0
#define a12 1403580.0
#define a13n 810728.0
#define a21 527612.0
#define a23n 1370589.0
/***
The seeds for s10, s11, s12 must be integers in [0, m1 - 1] and not all 0.
The seeds for s20, s21, s22 must be integers in [0, m2 - 1] and not all 0.
***/
#define SEED 100
static double s10 = SEED, s11 = SEED, s12 = SEED,
s20 = SEED, s21 = SEED, s22 = SEED;
double MRG32k3a (void)
{
long k;
double p1, p2;
/* Component 1 */
p1 = a12 * s11 - a13n * s10;
k = p1 / m1;
p1 -= k * m1;
if (p1 < 0.0)
p1 += m1;
s10 = s11;
s11 = s12;
s12 = p1;
/* Component 2 */
p2 = a21 * s22 - a23n * s20;
k = p2 / m2;
p2 -= k * m2;
if (p2 < 0.0)
p2 += m2;
s20 = s21;
s21 = s22;
s22 = p2;
/* Combination */
if (p1 <= p2)
return ((p1 - p2 + m1) * norm);
else
return ((p1 - p2) * norm);
}
int main()
{
double result = MRG32k3a();
printf("Result with seed 100 is: %f\n", result);
return (0);
}
Как уже отмечалось, мне нужно использовать этот генератор для создания двигателя, который можно подавать в единый реальный дистрибутив. Проблема в том, что я понятия не имею, как это делается, и я нигде не могу найти никакой информации (кроме знания того, что движки - это классы). Существуют ли какие-либо ресурсы C ++ 11, которые могут помочь мне в такой задаче? Я не прошу решения проблемы, а скорее указатели, которые помогут мне реализовать это самостоятельно.