我在R中使用replicate()函数生成随机数时遇到了问题。考虑R中的以下函数:
trial <- function(){rnorm(1)}
replicate(10, trial())它从高斯分布中产生10个随机数。它工作得非常好,并产生如下结果:
[1] 0.7609912 -0.2949613 1.8684363 -0.3358377 -1.6043926 0.2706250 0.5528813 1.0228125 -0.2419092 -1.4761937 但是,我有一个从高斯分布生成随机数c++函数getRan()。我再次使用replicate调用函数,如下所示:
replicate(10,getRan())它创建了一个具有相同数字的向量,如下所示:
> 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但是,如果我多次调用该函数,它工作得很好:
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++代码:
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;
}发布于 2018-05-26 22:57:38
下面是一个反例,说明它工作得很好:
代码
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:
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$ 发布于 2018-05-30 00:03:07
德克斯的答案是正确的。您应该使用R的RNG。如果您坚持在C++中使用RNG,您可以使用如下内容:
#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的影响。在这种情况下,按时间播种是更好的选择。
https://stackoverflow.com/questions/50543650
复制相似问题