문제

Boost :: Random의 MT19937 랜덤 번호 생성기를 사용하는 프로그램이 있습니다. 나는 무작위 _shuffle을 수행하고 Mersenne Twister의 이전에 생성 된 숫자와 관련하여 결정적이 될 수 있도록이 공유 상태에서 생성 된 랜덤 숫자가 생성되기를 원합니다.

나는 다음과 같은 것을 시도했다 :

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

그러나 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);
}

아마도 실제 기능 호출이기 때문일 것입니다. 그러나 분명히 이것은 원래 Mersenne Twister로부터 국가를 유지하지 않습니다. 무엇을 제공합니까? 글로벌 변수없이 내가하려는 일을 할 수있는 방법이 있습니까?

도움이 되었습니까?

해결책

C ++ 03에서는 기능-로컬 유형에 따라 템플릿을 인스턴스화 할 수 없습니다. RAND 클래스를 함수에서 옮기면 제대로 작동해야합니다 (면책 조항 : 테스트되지 않으면 다른 불길한 버그가있을 수 있습니다).

이 요구 사항은 C ++ 0X에서 완화되었지만 GCC의 C ++ 0X 모드에서 변경이 구현되었는지 여부는 모르겠습니다. 다른 컴파일러에 존재한다는 사실에 놀랐습니다.

다른 팁

이 의견에서 Robert Gould는 후손을위한 작업 버전을 요청했습니다.

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

Boost :: Random 대신 TR1을 사용하고 있지만 그다지 중요하지 않습니다.

다음은 약간 까다 롭지 만 작동합니다.

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

표준 라이브러리 만 사용하여 이것이 C ++ 11에서 꽤 간단하다는 것을 지적 할 가치가 있다고 생각했습니다.

#include <random>
#include <algorithm>

std::random_device rd;
std::mt19937 randEng(rd());
std::shuffle(vec.begin(), vec.end(), randEng);
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top