更改uniform_int_distribution的范围

时间:2013-09-26 18:41:26

标签: c++ c++11 random distribution

所以我有一个Random对象:

typedef unsigned int uint32;

class Random {
public:
    Random() = default;
    Random(std::mt19937::result_type seed) : eng(seed) {}

private:
    uint32 DrawNumber();
    std::mt19937 eng{std::random_device{}()};
    std::uniform_int_distribution<uint32> uniform_dist{0, UINT32_MAX};
};

uint32 Random::DrawNumber()
{
    return uniform_dist(eng);
}

我可以通过其他函数或其他方式改变分布的上限的最佳方式是什么?

(也愿意就其他风格问题提出建议)

3 个答案:

答案 0 :(得分:38)

分发对象很轻量级。当您需要随机数时,只需构建一个新的分布。我在游戏引擎中使用这种方法,并且在基准测试之后,它与使用好的旧rand()相当。

此外,我已经询问如何改变GoingNative 2013直播流的发行范围,标准委员会成员Stephen T. Lavavej建议简单地创建新的发行版,因为它不应该是一个表演问题。

以下是我编写代码的方法:

using uint32 = unsigned int;

class Random {
public:
    Random() = default;
    Random(std::mt19937::result_type seed) : eng(seed) {}
    uint32 DrawNumber(uint32 min, uint32 max);

private:        
    std::mt19937 eng{std::random_device{}()};
};

uint32 Random::DrawNumber(uint32 min, uint32 max)
{
    return std::uniform_int_distribution<uint32>{min, max}(eng);
}

答案 1 :(得分:8)

您只需创建std::uniform_int_distribution<uint32>::param_type并使用param()方法修改范围即可。您可以使用decltype

减少模板噪音
decltype(uniform_dist.param()) new_range (0, upper);
uniform_dist.param(new_range);

答案 2 :(得分:6)

我正在为我的例子制作DrawNumber函数public。您可以提供带有上限的重载,然后将新的uniform_int_distribution::param_type传递给uniform_int_distribution::operator()

可以使用与相应分布相同的参数构造param_type

来自N3337,§26.5.1.6/ 9 [rand.req.dist]

  

对于D的每个构造函数,它们采用与分布参数相对应的参数,P应具有相应的构造函数,这些构造函数具有相同的要求并且在数量,类型和默认值方面具有相同的参数。此外,对于返回与分布参数对应的值的D的每个成员函数,P应具有相同的成员函数,具有相同的名称,类型和语义。

其中D是随机数分布函数对象的类型,P是由D关联的param_type

命名的类型
#include <iostream>
#include <random>

typedef unsigned int uint32;

class Random {
public:
    Random() = default;
    Random(std::mt19937::result_type seed) : eng(seed) {}

    uint32 DrawNumber();
    uint32 DrawNumber(uint32 ub);

private:
    std::mt19937 eng{std::random_device{}()};
    std::uniform_int_distribution<uint32> uniform_dist{0, UINT32_MAX};
};

uint32 Random::DrawNumber()
{
    return uniform_dist(eng);
}

uint32 Random::DrawNumber(uint32 ub)
{
    return uniform_dist(eng, decltype(uniform_dist)::param_type(0, ub));
}

int main()
{
  Random r;
  std::cout << r.DrawNumber() << std::endl;
  std::cout << r.DrawNumber(42) << std::endl;
}