2014-01-08 37 views
0

我正在學習gsl_rng函數庫,發現一個有趣的問題。gsl_rng函數:按照什麼順序編譯

據我所知,環境變量(GSL_RNG_TYPEGSL_RNG_SEED)可以用來設置庫變量(gsl_rng_defaultgsl_rng_default_seed)在運行時(無需重新編譯)。您只需添加gsl_rng_env_setup(),然後在執行./a.out之前在終端中更改這兩個變量。但是,如果我在代碼中專門設置了gsl_rng_defaultgsl_rng_default _seed(例如使用「taus」和「12」),並且編譯了相同的程序,現在我不能在運行時更改種子值,但仍然可以更改發電機類型。

我是新來的這東西,所以可能我錯過了什麼。但誰能幫我理解爲什麼會發生這種情況?爲什麼這兩個變量的行爲不同?是否有命令或覆蓋寫入問題?

這裏是我的代碼(簡單的做法):

#include <stdio.h> 
#include <gsl/gsl_rng.h> 

int main (void) 
{ 
    const gsl_rng_type * T; /*generator type*/ 
    gsl_rng * r;   /*rng instance*/ 

    int i, n = 20; 

    gsl_rng_env_setup();  /*read from environment variable*/ 


    T = gsl_rng_default; /*choose default generator type*/ 

    gsl_rng_default = gsl_rng_mt19937; 
    gsl_rng_default_seed = 12; 

    r = gsl_rng_alloc (T); /*create an instance*/ 

    for (i = 0; i < n; i++) 
    { 
     double u = gsl_rng_uniform (r); 
     printf ("%.5f\n", u); 
    } 



    gsl_rng_free (r);  /*free all memory associated with r*/ 

return 0; 
} 

回答

0

如果我們通過在執行順序單步執行代碼,我們看看會發生什麼:

gsl_rng_env_setup();  /*read from environment variable*/ 

所以gsl_rnd_defaultgsl_rng_default_seed現在包含的值來自環境,或者如果他們沒有設置,庫默認。

T = gsl_rng_default; /*choose default generator type*/ 

T現在包含環境值的副本從早期

r = gsl_rng_alloc (T); /*create an instance*/ 

此時

gsl_rng_default = gsl_rng_mt19937; 
gsl_rng_default_seed = 12; 

我們現在已經覆蓋這兩個值,因爲gsl_rng_alloc()使用發電機類型我們傳遞參數,gsl_rng_default被覆蓋,因爲我們通過了T,並且那stil l預先包含它的值的副本。然而,由於gsl_rng_alloc()將繼續並使用當前的值gsl_rnd_default,它會得到我們放在那裏的12。

如果你調用gsl_rng_env_setup()之前指定默認值,你會覆蓋庫的默認值,然後將這些設置值將如果環境變量設置,或沒有通過,如果他們不被覆蓋,這看起來像你真正想要的行爲。

+0

我也會說混淆是可以原諒的,因爲這是一個非常糟糕的界面設計 - 有一個默認是寫入和隱式使用,一個「默認」,必須閱讀和顯式作爲參數傳遞是...有問題最好。 – Notlikethat

+0

謝謝你的回答!但正如您所說,由於執行順序,即使在程序讀取用戶的值(在gsl_rng_env_setup()之前發生)之後,我也會明確地將庫值覆蓋到mt19937和12。但是,該程序仍然使用任何生成器類型的用戶輸入,但堅持種子值12.因此,如果我在運行時輸入taus和4,程序使用taus和12作爲結果。這真的很奇怪。我預計這兩個變量的行爲方式都是一樣的 – CrazyFrog