32

所以我有一个随机对象:

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

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

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

4

3 回答 3

53

分布对象是轻量级的。当您需要一个随机数时,只需构建一个新的分布。我在游戏引擎中使用了这种方法,在基准测试之后,它与使用旧的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);
}
于 2013-09-26T18:52:37.580 回答
14

您可以使用该方法简单地创建std::uniform_int_distribution<uint32>::param_type和修改范围。param()您可以使用以下方法减少模板噪音decltype

decltype(uniform_dist.param()) new_range (0, upper);
uniform_dist.param(new_range);
于 2013-09-26T19:33:06.937 回答
7

我正在为我的示例制作DrawNumber函数public。您可以提供一个接受上限的重载,然后将新的传递uniform_int_distribution::param_typeuniform_int_distribution::operator()

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

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

对于每一个D取参数对应分布的参数的构造函数,P应有一个对应的构造函数,其要求相同,取参数的数量、类型和默认值都相同。而且,对于D那个返回值对应的分布参数的每个成员函数,P都应该有一个对应的成员函数,其名称、类型和语义都相同。

其中D是随机数分布函数对象的类型,是由的关联P命名的类型Dparam_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;
}
于 2013-09-26T18:54:52.987 回答