2013-09-26 32 views
19

范围所以我有一个随机的对象:而变化uniform_int_distribution

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

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

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

+0

后第一初始化它们不能改变'distribution'的边界。你应该如何继续下去,很大程度上取决于你使用随机数的原因以及为什么你需要改变边界。 – us2012

回答

32

分布对象是轻量级的。当你需要一个随机数时,简单地构造一个新的分布。我在游戏引擎中使用这种方法,并且在基准测试之后,它可以使用好的旧版本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); 
} 
+0

我想我只是看着本地流:)虽然,我(有点)新的C + +(特别是C + + 11)和相当数量的它在我的头上:L 如果你确定每次创建一个新的发行版本都没有很大的开销,我可能会用这个 – LordAro

+0

去做基准测试。开销很小,可以忽略。 (这是由一个微型优化纳粹说)。 此外,还有*没有其他方式可以改变分布的边界。 –

+0

好,很好,非常感谢:) 我可能会用一个常数0作为最小走,UINT32_MAX作为最大默认。 – LordAro

5

我正在做的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是相关联的由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; 
} 
8

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

decltype(uniform_dist.param()) new_range (0, upper); 
uniform_dist.param(new_range);