更改uniform_int_distribution的范围

Lor*_*Aro 23 c++ random distribution c++11

所以我有一个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);
}
Run Code Online (Sandbox Code Playgroud)

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

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

Vit*_*meo 41

分发对象是轻量级的.当您需要随机数时,只需构建一个新的分布.我在游戏引擎中使用这种方法,并且在基准测试之后,它与使用旧版本相当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);
}
Run Code Online (Sandbox Code Playgroud)

  • 我已经对其进行了基准测试。开销很小,可以忽略。(这是一个微优化纳粹所说的)。此外,没有其他方法可以改变分布的边界。 (2认同)
  • 这*创建*了一个新的发行版,而不是修改现有的发行版。因此,无论类的实例化速度有多快,它都无法回答问题。 (2认同)

Bre*_*ale 8

您只需std::uniform_int_distribution<uint32>::param_type使用该param()方法创建并修改范围即可.您可以使用以下方法减少模板噪音decltype:

decltype(uniform_dist.param()) new_range (0, upper);
uniform_dist.param(new_range);
Run Code Online (Sandbox Code Playgroud)


Pra*_*ian 6

我正在为我的例子做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应具有相同的成员函数,其具有相同的名称,类型和语义.

where 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;
}
Run Code Online (Sandbox Code Playgroud)