How to set the parameters of boost::uniform_int_di

2019-04-17 07:37发布

I am using a uniform_int_distribution in Boost 1.52 to generate random numbers using the basic boilerplate code:

#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int_distribution.hpp>

boost::random::mt19937 gen;

int roll_die()
{
    boost::random::uniform_int_distribution<> dist(1, 6);
    return dist(gen);
}

int main()
{
    for (int i = 0; i < 10; i++) std::cout << roll_die() << std::endl;     
}

I implemented parts of this in a much larger project and it works great. Here is my question.

In the above function, it seems like the dist object is local to the function. If you call roll_die() many many times, it seems like having dist() be local to the function would introduce a lot of overhead.

I'm thinking it would be better to set the min and max parameters of this object once, and then only have one instance of dist in a bigger object or something. How does one do this? I tried to understand the "Public Member Functions" portion of the class template: http://www.boost.org/doc/libs/1_47_0/doc/html/boost/random/uniform_int_distribution.html#id744736-bb but it was over my head. In that documentation I see:

void param(const param_type & param); //Sets the parameters of the distribution.

How do you actually use this? Is .param() itself a function to call, or is it a stand-in for another function? I couldn't find another boost example that did what I'm asking. Thanks in advance for your assistance and advice!

1条回答
仙女界的扛把子
2楼-- · 2019-04-17 08:06

it seems like ... would introduce a lot of overhead.

You may assume it does, but do you actually know this? You should not make any assumptions if anything is faster or slower without actually running a profiler or benchmarking the code in some other way. If you look at the source, you can see that uniform_int_distribution's constructor merely assigns the min and max values - which should be really insignificant overhead. Especially if you take into account that the actual random number generation will be a much more complex operation than two assignments. So I'd suggest you leave the code as is, and if your program is too slow, you can always profile and then optimize.

Edit: To quote Djikstra: "Premature optimization is the root of all evil". Way too often, programmer's write more complex code than need be, simply because they think it will be faster. Don't do it - only start optimizing when there are speed problems.

Anyway, to answer your questions: param() is a member of uniform_int_distribution. It takes an object of type uniform_int_distribution::param_type. You can use it like so:

using namespace boost::random;

// Create an uniform_int_distribution object
uniform_int_distribution<> dist(1, 6);

// Create a params object
uniform_int_distribution::param_type newParams(10, 500);

// The following will reconfigure dist to have 10 and 500 as 
// min and max value
dist.param(newParams);

This way, you can reconfigure a single distribution object as often as you like. But the "overhead" will likely be the same as constructing a new distribution object.

Another way you can ensure that the object is only created once:

int roll_die()
{
    static boost::random::uniform_int_distribution<> dist(1, 6);
    return dist(gen);
}

Declaring variables inside of functions as static has a similar effect as if the variable where global, but it's only visible in the function's scope.

查看更多
登录 后发表回答