4

这是一个 C++ 函数,用于绘制N具有均值零和标准差的独立正态偏差s

// [[Rcpp::depends(RcppArmadillo)]]

#include <RcppArmadillo.h>
using namespace Rcpp;

// [[Rcpp::export]] 
List rnorm_cpp(double s, int N){

    arma::colvec epsilon = s * arma::randn(N);
    return List::create(Named("e") = epsilon);

}

这是一个(几乎相同的)R版本

rnormR <- function(s, N){

  epsilon <- rnorm(N, mean = 0, sd = s)
  return(list(e = epsilon))

}    

采购后rnorm_cpprnormR我运行了以下命令:

set.seed(1234)
fooR <- rnormR(s = 5, N = 10)

set.seed(1234)
barR <- rnormR(s = 5, N = 10)

set.seed(1234)
fooCpp <- rnorm_cpp(s = 5, N = 10)

set.seed(1234)
barCpp <- rnorm_cpp(s = 5, N = 10)

最后,我运行identical并得到以下结果:

> identical(fooR, barR)
[1] TRUE
> identical(barR, fooCpp)
[1] FALSE
> identical(fooCpp, barCpp)
[1] FALSE

我期待得到TRUE所有这三个。我怎样才能:(1)在调用中复制随机抽奖和(2)在调用和时rnorm_cpp获得相同的抽奖?rnormRrnorm_cpp

4

1 回答 1

7

该函数arma::randn()未连接到 R RNG,因此调用对其没有set.seed()影响。

我们在 Rcpp 中所做的是利用精细的 R API,它允许我们从 R 和 C++访问相同的 RNG。通过小心处理RNGScope实例(自动插入),RNG 状态在 R 和 C++ 之间始终是正确的。

但是您根本不能假设任何其他第三方 RNG(这里:Arma's)也自动对齐。此外,在这种特殊情况下,康拉德的犰狳文档很清楚:

要更改种子,请使用std::srand()函数

为了澄清(嗨,@DWin)这里是完整的 R 和 C++ 示例:

R> set.seed(42); rnorm(5)           ## Five N(0,1) draws in R
[1]  1.3710 -0.5647  0.3631  0.6329  0.4043
R> cppFunction('NumericVector foo(int n) { return rnorm(n); }')
R> set.seed(42); foo(5)             ## Five N(0,1) draws from C++ fun.
[1]  1.3710 -0.5647  0.3631  0.6329  0.4043
R> 

我们通过 R 和 C++ 获得相同的数字,因为我们 a)对 RNG 进行相同的播种,并且 b)实际上调用了 R 提供的相同 RNG。

于 2013-10-01T01:00:57.687 回答