2011-06-24 77 views
2

如果已經討論過,請原諒我。我有它使用的boost :: uniform_int和boost ::取決於模板參數uniform_real,應返回相同類型的模板函數:boost :: random和boost:uniform_real與雙精度浮點數一起工作嗎?

template <typename N> N getRandom(int min, int max) 
{ 
    timeval t; 
    gettimeofday(&t,NULL); 
    boost::mt19937 seed((int)t.tv_sec); 
    boost::uniform_int<> dist(min, max); 
    boost::variate_generator<boost::mt19937&, boost::uniform_int<> > random(seed, dist); 
    return random(); 
} 
//! partial specialization for real numbers 
template <typename N> N getRandom(N min, N max) 
{ 
    timeval t; 
    gettimeofday(&t,NULL); 
    boost::mt19937 seed((int)t.tv_sec); 
    boost::uniform_real<> dist(min,max); 
    boost::variate_generator<boost::mt19937&, boost::uniform_real<> > random(seed,dist); 
    return random(); 
} 

現在我已經測試使用int,float和雙打功能。 它工作正常與int,它工作正常與雙,但它不適用於浮動。就好像它將float轉換爲int,或者存在一些轉換問題。我說這是因爲當我這樣做:

float y = getRandom<float>(0.0,5.0); 

我總是得到一個int回來。然而,就像我說的那樣,它適用於雙打。 有什麼我做錯了或失蹤? 謝謝!

+1

亞歷克斯,你不應該以這種方式產生隨機數。每次調用函數時都會重新生成種子,這意味着您失去了一個好的PRNG可以給你的所有好的保證。您生成的數字實際上可能是「非隨機」。 – Richard

+0

@Richard您是第一個觀察此人的人!差不多兩年前我問過這個問題,沒有人注意到。是的,你是完全正確的,我這樣毀了PRNG。每當我需要一個合適的PRNG時,我就一直使用Mersenne Twister。謝謝你提到它:) –

回答

7

參數0.0,5.0是雙打,而不是浮動。讓他們漂浮:

float y = getRandom<float>(0.0f,5.0f); 
+0

謝謝,看到我不知道。 –

5

沒有真正解決你的問題本身,而是一個解決方案:

爲什麼不使用traits類,以得到正確的分佈類型?

template<class T> 
struct distribution 
{ // general case, assuming T is of integral type 
    typedef boost::uniform_int<> type; 
}; 

template<> 
struct distribution<float> 
{ // float case 
    typedef boost::uniform_real<> type; 
}; 

template<> 
struct distribution<double> 
{ // double case 
    typedef boost::uniform_real<> type; 
}; 

有了那一套,你可以有一個一般的功能:

template <typename N> N getRandom(N min, N max) 
{ 
    typedef typename distribution<N>::type distro_type; 

    timeval t; 
    gettimeofday(&t,NULL); 
    boost::mt19937 seed((int)t.tv_sec); 
    distro_type dist(min,max); 
    boost::variate_generator<boost::mt19937&, distro_type > random(seed,dist); 
    return random(); 
}; 
+0

這是一個更優雅的解決方案,謝謝 –

+0

不應使用此代碼。它在每次通話中都會重新生成種子,這基本上破壞了PRNG的目的。 – Richard

+2

@理查德:請原諒我解決OP的問題 - 選擇正確的分配。你真的認爲這值得讚揚嗎?這個答案「沒用」嗎? – Xeo

7

你甚至可以在避免與類型特徵和MPL編寫樣板代碼:

template <typename N> 
N getRandom(N min, N max) 
{ 
    typedef typename boost::mpl::if_< 
    boost::is_floating_point<N>, // if we have a floating point type 
    boost::uniform_real<>,  // use this, or 
    boost::uniform_int<>   // else use this one 
    >::type distro_type; 

    timeval t; 
    gettimeofday(&t,NULL); 
    boost::mt19937 seed((int)t.tv_sec); 
    distro_type dist(min,max); 
    boost::variate_generator<boost::mt19937&, distro_type > random(seed,dist); 
    return random(); 
}; 
+1

不應使用此代碼。它在每次通話中都會重新生成種子,這基本上破壞了PRNG的目的。 – Richard