2008-09-29 88 views
11

我有一個使用boost :: random的mt19937隨機數生成器的程序。我需要做一個random_shuffle,並且希望爲此生成的隨機數來自這個共享狀態,這樣他們就可以確定mersenne twister先前生成的數字。使用boost :: random作爲std :: random_shuffle的RNG

我想是這樣的:

void foo(std::vector<unsigned> &vec, boost::mt19937 &state) 
{ 
    struct bar { 
     boost::mt19937 &_state; 
     unsigned operator()(unsigned i) { 
      boost::uniform_int<> rng(0, i - 1); 
      return rng(_state); 
     } 
     bar(boost::mt19937 &state) : _state(state) {} 
    } rand(state); 

    std::random_shuffle(vec.begin(), vec.end(), rand); 
} 

但我得到一個模板錯誤調用random_shuffle與蘭特。然而,這個工程:

unsigned bar(unsigned i) 
{ 
    boost::mt19937 no_state; 
    boost::uniform_int<> rng(0, i - 1); 
    return rng(no_state); 
} 
void foo(std::vector<unsigned> &vec, boost::mt19937 &state) 
{ 
    std::random_shuffle(vec.begin(), vec.end(), bar); 
} 

可能是因爲它是一個實際的函數調用。但顯然這並不能保持原來的梅森扭曲者的狀態。是什麼賦予了?有沒有辦法做我沒有全局變量要做的事情?

+0

一旦你測試一下,你能請張貼正確的代碼,爲了後代?謝謝 – 2008-09-29 03:39:41

+0

Greg:我已經恢復了你的改變。如果您願意使用Markdown代碼塊(每行縮進4個空格),則無需在代碼中轉義HTML字符。 – 2008-09-29 03:43:44

+0

只需突出顯示代碼,然後單擊「010 101」按鈕。 – 2008-09-29 03:44:15

回答

11

在C++ 03中,您無法基於函數本地類型實例化模板。如果你將rand類移出函數,它應該可以正常工作(免責聲明:未經測試,可能還有其他不祥之兆)。

這個要求在C++ 0x中已經放寬了,但是我不知道這個改變是否已經在GCC的C++ 0x模式中實現了,而且我會驚奇的發現它存在於任何其他的編譯器中。

13

在評論中,羅伯特·古爾德問一個工作版本供後人:

#include <algorithm> 
#include <functional> 
#include <vector> 
#include <boost/random.hpp> 

struct bar : std::unary_function<unsigned, unsigned> { 
    boost::mt19937 &_state; 
    unsigned operator()(unsigned i) { 
     boost::uniform_int<> rng(0, i - 1); 
     return rng(_state); 
    } 
    bar(boost::mt19937 &state) : _state(state) {} 
}; 

void foo(std::vector<unsigned> &vec, boost::mt19937 &state) 
{ 
    bar rand(state); 
    std::random_shuffle(vec.begin(), vec.end(), rand); 
} 
5

我使用TR1代替的boost ::隨機這裏,但應該沒有多大關係。

以下是有點棘手,但它的作品。

#include <algorithm> 
#include <tr1/random> 


std::tr1::mt19937 engine; 
std::tr1::uniform_int<> unigen; 
std::tr1::variate_generator<std::tr1::mt19937, 
          std::tr1::uniform_int<> >gen(engine, unigen); 
std::random_shuffle(vec.begin(), vec.end(), gen); 
1

我認爲這是值得指出的是,這僅使用標準庫現在是在C++ 11很簡單:

#include <random> 
#include <algorithm> 

std::random_device rd; 
std::mt19937 randEng(rd()); 
std::shuffle(vec.begin(), vec.end(), randEng); 
相關問題