2012-12-29 64 views
5

我在R代碼中製作C。傳遞種子/在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") 

感謝。

回答

7

這是你的思維邏輯錯誤 - 你正確設置種子,從初始化代碼將R RNG ...但隨後致電系統RNG,而不是將R RNG的。

rand()替換爲unif_rand()(或norm_rand()),您應該設置。

Rcpp使所有這些變得更容易,併爲您提供矢量化的訪問以從各種分佈函數中繪製(但如果您願意的話,您當然也可以在C中完成所有這些工作)。

通過使用cppFunction()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的。

+0

One liner!真的很強大! – agstudy

+0

是的,雖然'cppFunction()'在幕後做了一些魔術來使這條線生效 - 它確實得到了擴展。但是對於我們來說,它非常接近魔法;-) –

+0

但是我最好是使用sourceCpp(至少用於調試目的)? – agstudy