6

我在 R 代码中制作 C。

在我的 C 代码中,我使用 rand() 函数来生成随机数。R-ext.pdf 说我必须使用命令设置种子;

  GetRNGstate();
  PutRNGstate();

尽管我在上面使用这些命令,但对于同一个种子,我仍然得到不同的值。你能给我任何帮助吗?

最小的例子是:

在 C 中:

# include <R.h>
# include <Rinternals.h>
# include <Rmath.h>
# include <R_ext/Linpack.h> 

 SEXP example(){

   SEXP output;
   GetRNGstate();
   PROTECT(output = allocVector(INTSXP, 1));
   INTEGER(output)[0] = rand() % 50;
   PutRNGstate();
   UNPROTECT(1);
   return(output);
 }

在 R 中:

dyn.load("example.so")
## The following codes return different values at ever run 
set.seed(1)
.Call("example")

提前致谢。

4

1 回答 1

8

这是您的想法中的一个逻辑错误——您正确设置了种子,从代码中初始化了 R RNG ...但随后调用了系统 RNG而不是 R RNG。

替换rand()unif_rand()(或norm_rand()),您应该已设置好。

Rcpp使这一切变得更容易,并让您可以从各种分布函数中对绘图进行矢量化访问(但如果您愿意,当然也可以在 C 中手动完成所有这些操作)。

通过使用cppFunction()from Rcpp,我们现在还负责RNGScope依次提供GetRNGstate()/ PutRNGstate()(虽然旧示例仍然显示 ; 的实例化,RNGScope添加它并没有什么害处,因为它相当于引用计数)。

所以定义、自动扩展、编译和加载它确实是一条线:

R> cppFunction("double myrand() { return norm_rand(); }")
R> for (i in 1:5) { set.seed(42); cat(i, " -- ", myrand(), "\n") }
1  --  1.37096 
2  --  1.37096 
3  --  1.37096 
4  --  1.37096 
5  --  1.37096 
R> 

而没有我们得到的重新播种

R> for (i in 1:5) { cat(i, " -- ", myrand(), "\n") }
1  --  -0.564698 
2  --  0.363128 
3  --  0.632863 
4  --  0.404268 
5  --  -0.106125 
R> 

最后,如果您真的想要,您当然可以继续使用rand()(但请参阅有关其糟糕性能的文献),然后使用其播种功能而不是 R 的。

于 2012-12-29T04:17:32.097 回答