我在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")
提前致谢。
答案 0 :(得分:7)
这是您思考中的逻辑错误 - 您正确设置种子,从代码初始化R RNG ...但是然后调用系统RNG 而不是R RNG。
将rand()
替换为unif_rand()
(或norm_rand()
),您应该进行设置。
Rcpp使所有这一切变得更加容易,并且您可以从各种分发函数中获取对绘图的矢量化访问权限(但如果您愿意,您当然可以在C中手动完成所有这些操作)。
通过使用Rcpp中的cppFunction()
,我们现在还会处理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()
最后,如果您真的希望您当然可以继续使用{{1}}(但请参阅有关其糟糕性能的文献),然后使用其播种功能而不是R的。