当前位置: 首页 > 知识库问答 >
问题:

在C++11中为创建匹配PRNG结果的PRNG引擎

艾学海
2023-03-14

这个问题是双重的。我正在将一个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之间的一个相关示例。利用R:

seednum<-100
set.seed(seednum, kind="Mersenne-Twister")
runif(1)
#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问题为我澄清了这一点(如上面链接的)。似乎在R中有一些传递给MRG32k3a的参数,我需要在C++中复制这些参数,以便生成相同的随机数。因此,第一个问题是,我在哪里可以找到R中的MRG32k3a实现的文档,该文档指定了这些参数?

第二个问题是用C++11实现这个生成器。此生成器不出现在此处列出的C++11的 库中的预配置引擎类型列表中。在这里可以找到用C实现的MRG32k3a的示例,如下所示:

/*
   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资源可以帮助我完成这样的任务?我要求的不是解决问题的办法,而是帮助我自己实现这个目标的指针。

共有1个答案

葛念
2023-03-14

因此,第一个问题是,我在哪里可以找到R中的MRG32k3a实现的文档,该文档指定了这些参数?

我将使用来源:https://github.com/wch/r-source/blob/5a156a0865362bb8381dcd69ac335f5174a4f60c/src/main/rng.c#l143

问题是我不知道这是如何实现的,而且我似乎在任何地方都找不到任何信息(除了知道引擎是类之外)。

Expression      Return type     Requirements
G::result_type  T               T is an unsigned integer type
G::min()        T               Returns the smallest value that G's operator()
                                may return. The value is strictly less than
                                G::max().
G::max()        T               Returns the largest value that G's operator() may
                                return. The value is strictly greater than
                                G::min()
g()             T               Returns a value in the closed interval [G::min(),
                                G::max()]. Has amortized constant complexity.  
    null

替代方法包括直接使用R源代码,而不与 头或到libr的链接集成。

 类似资料:
  • 问题内容: 我想知道Java中PRNG *的默认种子是什么。据我了解,C语言中的一个基于系统时钟。在Java中是否类似?另外,每次调用都改变种子了吗? PRNG =伪随机数生成器 问题答案: 如果您阅读精美的手册,它会告诉您 首次调用此方法时,它会创建一个新的伪随机数生成器,就像通过表达式 此新的伪随机数生成器此后将用于此方法的所有调用,并且在其他任何地方均不使用。 跟进,文件说 创建一个新的随机

  • 我有一个接口,它提供了一个方法,返回一个,其中包含一个

  • 问题内容: 做一个简单的测试时,我就在用Java编写正则表达式 但是在JavaScript中 这里发生了什么?我可以使我的Java regex模式“ q”的行为与JavaScript相同吗? 问题答案: 在JavaScript中,返回与使用的正则表达式匹配的子字符串。在Java中,检查整个字符串是否与正则表达式匹配。 如果要查找与正则表达式匹配的子字符串,请使用Pattern和Matcher类,例

  • 我似乎看到了许多答案,其中有人建议使用生成随机数,通常与下面这样的代码一起生成: 通常这会取代某种“不神圣的可憎之物”,例如: 可以(有时)实现为具有固定种子的简单PRNG。因此,它可能在每次运行时产生相同的序列。(链接)这比还要糟糕。 更糟糕的是,复制和粘贴前面的代码段非常容易,尽管它们包含问题。一些解决方案需要获取大型图书馆,但这并不适合所有人。 有鉴于此,我的问题是如何在C++中简洁、可移植

  • 我正在考虑从主线程创建、的可能性,而分离的线程创建线程并等待之后再运行下一个线程。 但我不认为这是可能的,因为我总是在第一个线程之后而在下一个线程之前崩溃。 : : 因此,以下是我希望发生的事情: 更新:如何接受这个并将其分解,以便在标头中声明,但在需要的地方执行,然后执行