C++11 生成频繁变化范围内的随机数

8

问:如何从先验未知的范围中生成(许多)均匀分布的整数?在性能方面,什么是首选方法(生成数百万个数字)?

背景:在我的应用程序中,我必须在许多地方生成许多伪随机数。我使用单例模式来维护应用程序运行的可重现性。在我的情况下,分布总是均匀的,但问题在于有太多可能的范围无法在C++11样式中预先制作分布对象。

我尝试过的方法:这有两个明显的解决方案,第一个是拥有一次性分布对象,第二个是使用取模将随机数从最广泛的范围转换为所需的范围。但我对这些是否是最佳解决方案表示怀疑 :)

#include <random>
#include <iostream>
#include "limits.h"
using namespace std;

mt19937 mt;
uniform_int_distribution<int> * fixedDist;
uniform_int_distribution<int> * variableDist;

// this version creates and delete dist after just one use
int getIntFromRange1(int from, int to){
    variableDist = new uniform_int_distribution<int>(from,to);
    int num = (*variableDist)(mt);
    delete variableDist;
    return num;
}

// this version contains modulo
int getIntFromRange2(int from, int to){
    int num = (*fixedDist)(mt);
    int diff = to - from;
    num = num % diff;
    return num + from;
}

int main(){ 
   mt.seed(123456);
   fixedDist= new uniform_int_distribution<int>(0,INT_MAX)

   int a = getIntFromRange1(1,10); // 1 and 10 are just for illustration
   int b = getIntFromRange2(1,10); // can change freely

   cout << "a: " << a << endl; // a: 6
   cout << "b: " << b << endl; // b: 9

   getchar();
}

重复问题

更改 uniform_int_distribution 的范围

2个回答

10

我会去做。

int getIntFromRange1(int from, int to){
    std::uniform_int_distribution<int> dist(from, to);
    return dist(mt);
}

这比我的好一点,我承认 :-) - teejay
1
这是你能得到的最好的。uniform_int_distribution只是两个值的占位符(param_type的包装器,类似于pair)。编译器会优化它得很好(没有涉及分配)。 - firda
那我猜我得接受这个答案了,谢谢大家的帮助! - teejay

0

我会像Jarod42的回答中所说的那样进行:分布对象应该是轻量级的,因此在需要随机数时构建新的分布是简单快速的(昂贵的是随机引擎)。

但是你也可以考虑这种实现:

inline int get_int_from_range(int from, int to)
{
  using distribution_type = std::uniform_int_distribution<int>;
  using param_type = typename distribution_type::param_type;

  thread_local distribution_type dist;
  return dist(mt, param_type(from, to));
}

这样做的原因是可能有需要存储值/状态的分布。

对于整数和均匀分布来说,可能并不是这种情况,但在N4316 - std::rand replacement中,建议的实现使用了这种技术,这很有趣。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接