Frage

Ich habe ein Programm, das den MT19937 Zufallszahlengenerator von boost :: verwendet zufällig. Ich brauche eine random_shuffle und will die Zufallszahl für das aus diesem freigegebenen Zustand zu sein, erzeugt zu tun, so dass sie in Bezug auf die der Mersenne-Twister-vorher erzeugten Zahlen deterministisch sein können.

habe ich versucht, so etwas wie folgt aus:

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);
}

Aber ich bekomme eine Vorlage Fehler mit rand Aufruf random_shuffle. Doch dies funktioniert:

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);
}

Wahrscheinlich, weil es sich um einen tatsächlichen Funktionsaufruf. Aber offensichtlich ist dies nicht hält den Zustand von dem ursprünglichen Mersenne-Twister-. Was gibt? Gibt es eine Möglichkeit zu tun, was ich versuche, ohne globale Variablen zu tun?

War es hilfreich?

Lösung

In C ++ 03, können Sie nicht eine Vorlage instanziiert auf einem funktions lokalen Typ. Wenn Sie den Rand Klasse aus der Funktion zu bewegen, sollte es funktionieren (Disclaimer: nicht getestet, könnte es andere finstere Fehler sein).

Diese Anforderung wurde in C ++ 0x entspannt, aber ich weiß nicht, ob die Änderung der GCC C ++ 0x-Modus noch nicht umgesetzt wurde, und ich wäre sehr überrascht, dass es in jedem anderen Compiler vorhanden zu finden.

Andere Tipps

In den Kommentaren, Robert Gould für eine funktionierende Version für die Nachwelt gefragt:

#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);
}

Ich bin mit tr1 statt boost :: zufällig hier, sollte aber nicht viel aus.

Im Folgenden ist ein bisschen schwierig, aber es funktioniert.

#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);

Ich dachte, es wert war, weist darauf hin, dass dies in C jetzt ziemlich einfach nur die Standard-Bibliothek ++ 11 mit:

#include <random>
#include <algorithm>

std::random_device rd;
std::mt19937 randEng(rd());
std::shuffle(vec.begin(), vec.end(), randEng);
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top