代码之家  ›  专栏  ›  技术社区  ›  Greg Rogers

使用boost::random作为std::random随机移动的rng

  •  11
  • Greg Rogers  · 技术社区  · 17 年前

    我有一个使用Boost::Random的MT19937随机数生成器的程序。我需要做一个随机的洗牌,并希望为此生成的随机数来自这个共享状态,这样它们就可以对梅森缠绕器先前生成的数具有确定性。

    我试过这样的方法:

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

    但是我得到了一个模板错误调用随机随机随机随机随机随机随机移动。然而,这是可行的:

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

    可能是因为它是一个实际的函数调用。但很明显,这并不能阻止国家从原来的梅森龙卷风。什么给予?在没有全局变量的情况下,有什么方法可以做到我想做的事情吗?

    4 回复  |  直到 11 年前
        1
  •  11
  •   coppro    17 年前

    在C++ 03中,不能基于函数局部类型实例化模板。如果您将rand类移出函数,它应该可以正常工作(免责声明:未测试,可能还有其他危险的bug)。

    这个要求在C++0X中已经被放宽了,但是我不知道这个改变是否已经在GCC的C++ 0x模式中实现了,我会很惊讶地发现它存在于任何其他编译器中。

        2
  •  13
  •   C. K. Young    17 年前

    在评论中,罗伯特·古尔德要求为子孙后代提供一个工作版本:

    #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);
    }
    
        3
  •  5
  •   user1202136    13 年前

    我使用的是TR1而不是Boost::Random,但不太重要。

    下面是一个有点棘手的问题,但它是有效的。

    #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);
    
        4
  •  1
  •   Eliot    11 年前

    我认为值得指出的是,现在在C++ 11中使用标准库是非常简单的:

    #include <random>
    #include <algorithm>
    
    std::random_device rd;
    std::mt19937 randEng(rd());
    std::shuffle(vec.begin(), vec.end(), randEng);