首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >R replicate()函数对Rcpp函数无效

R replicate()函数对Rcpp函数无效
EN

Stack Overflow用户
提问于 2018-05-26 22:15:21
回答 2查看 234关注 0票数 0

我在R中使用replicate()函数生成随机数时遇到了问题。考虑R中的以下函数:

代码语言:javascript
复制
trial <- function(){rnorm(1)}
replicate(10, trial())

它从高斯分布中产生10个随机数。它工作得非常好,并产生如下结果:

代码语言:javascript
复制
 [1]  0.7609912 -0.2949613  1.8684363 -0.3358377 -1.6043926  0.2706250  0.5528813  1.0228125 -0.2419092 -1.4761937 

但是,我有一个从高斯分布生成随机数c++函数getRan()。我再次使用replicate调用函数,如下所示:

代码语言:javascript
复制
replicate(10,getRan())

它创建了一个具有相同数字的向量,如下所示:

代码语言:javascript
复制
> replicate(10,getRan())
 [1] -1.374932 -1.374932 -1.374932 -1.374932 -1.374932 -1.374932 -1.374932 -1.374932 -1.374932 -1.374932
> replicate(10,getRan())
 [1] -0.3273785 -0.3273785 -0.3273785 -0.3273785 -0.3273785 -0.3273785 -0.3273785 -0.3273785 -0.3273785 -0.3273785
> replicate(10,getRan())
 [1] -0.7591953 -0.7591953 -0.7591953 -0.7591953 -0.7591953 -0.7591953 -0.7591953 -0.7591953 -0.7591953 -0.7591953
> replicate(10,getRan())
 [1] -1.698935 -1.698935 -1.698935 -1.698935 -1.698935 -1.698935 -1.698935 -1.698935 -1.698935 -1.698935

但是,如果我多次调用该函数,它工作得很好:

代码语言:javascript
复制
 getRan()
[1] 1.345227
> getRan()
[1] 0.3555393
> getRan()
[1] 1.587241
> getRan()
[1] 0.5313518

那么这里的问题是什么呢?replicate()函数是否重复从getRan()返回的相同函数,而不是多次调用getRan()?这是个bug吗?

PS:我知道我可以使用rnorm(n)生成n个正态随机数,但是,我想使用c++函数在生成随机数的基础上进行更复杂的计算

PPS:这是我的c++代码:

代码语言:javascript
复制
double getRan(){
  unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
  std::default_random_engine generator(seed);
  std::normal_distribution<double> distribution (0.0,1.0);
  double epi = distribution(generator);
  return epi;
}
EN

回答 2

Stack Overflow用户

发布于 2018-05-26 22:57:38

下面是一个反例,说明它工作得很好:

代码

代码语言:javascript
复制
trialR <- function() { rnorm(1) }
Rcpp::cppFunction("double trialC() { return R::rnorm(0.0, 1.0); }")
Rcpp::cppFunction("Rcpp::NumericVector trialSugar() { return Rcpp::rnorm(1.0, 0.0, 1.0); }")

set.seed(123); replicate(3, trialR())
set.seed(123); replicate(3, trialC())
set.seed(123); replicate(3, trialSugar())

输出

通过Rscript确保新会话等pp:

代码语言:javascript
复制
edd@rob:/tmp$ Rscript so50543659.R 
[1] -0.560476 -0.230177  1.558708
[1] -0.560476 -0.230177  1.558708
[1] -0.560476 -0.230177  1.558708
edd@rob:/tmp$ 
票数 2
EN

Stack Overflow用户

发布于 2018-05-30 00:03:07

德克斯的答案是正确的。您应该使用R的RNG。如果您坚持在C++中使用RNG,您可以使用如下内容:

代码语言:javascript
复制
#include <Rcpp.h>
// [[Rcpp::plugins(cpp11)]]
#include <random>

namespace {
  std::default_random_engine generator(std::random_device{}());
  std::normal_distribution<double> distribution (0.0,1.0);  
}

// [[Rcpp::export]]
double getRan(){
  return distribution(generator);
}

/*** R
replicate(10,getRan())
*/

这避免了在每次函数调用时创建std::default_random_engine (和std::normal_distribution)的新实例。这一点很重要,因为RNG的属性只能保证从一个RNG中重复绘制。而不是重复地从不同的RNG中提取种子(希望是不同的)种子。

顺便说一句,在我的系统上,你的原始代码不会多次产生相同的数字。如果您在使用std::random_device时遇到问题,并且正在使用windows,则可能会受到this mingw bug的影响。在这种情况下,按时间播种是更好的选择。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50543650

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档