2012-06-12 13 views
13

Sto cercando di utilizzare l'approccio C++ 11 di generazione di numeri casuali:Come resettare un motore di numeri casuali?

#include <random> 
#include <functional> 
#include <iostream> 

int main(int argc, char *argv[]) 
{  
    std::normal_distribution<double> normal(0, 1); 
    std::mt19937 engine; // Mersenne twister MT19937 
    auto generator = std::bind(normal, engine); 

    int size = 2; 

    engine.seed(0); 
    normal.reset(); 
    for (int i = 0; i < size; ++i) 
     std::cout << generator() << std::endl; 

    std::cout << std::endl; 

    engine.seed(1); 
    normal.reset(); 
    for (int i = 0; i < size; ++i) 
     std::cout << generator() << std::endl; 

    std::cout << std::endl; 

    engine.seed(0); 
    normal.reset(); 
    for (int i = 0; i < size; ++i) 
     std::cout << generator() << std::endl; 

    return 0; 
} 

Il risultato è:

0.13453 
-0.146382 

0.46065 
-1.87138 

0.163712 
-0.214253 

Ciò significa che la prima e la terza sequenza non sono identici, anche se sono seminati con lo stesso numero. Per favore, cosa sto sbagliando? È il

std::normal_distribution<double> 

solo una funzione in senso matematico (y produce fuori x deterministicamente) o mi sto perdendo qualcosa? Se è solo una funzione, cosa fa effettivamente il metodo di reset?

risposta

19

Si sta vincolando il motore e la distribuzione, ad esempio le seguenti chiamate al ripristino non influiranno sulla funzione associata.

La soluzione è quella di legare i riferimenti al motore e la distro

auto generator = std::bind(std::ref(normal), std::ref(engine)); 
+0

È stato. Suppongo di dover imparare molto più l'STL :) Funziona perfettamente con la tua soluzione. Grazie! –

+0

'auto generator = std :: bind (normale, std :: ref (engine)); è abbastanza suppongo. – Tengis

11

Il problema riscontrato è con std::bind. std::bind fa copie dei suoi argomenti. Il motivo std::bind crea copie perché la funzione verrà chiamata in un punto sconosciuto in futuro quando gli argomenti potrebbero non esistere più. Ciò significa che le chiamate a engine.seed(), ecc. Sono inutili. Usando std::ref puoi associare i tuoi argomenti per riferimento che ti darà l'output atteso.

auto generator = std::bind(std::ref(normal), std::ref(engine)); 
+0

Grazie! Era così. Ora funziona bene! :) –