首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >从一个范围生成随机整数

从一个范围生成随机整数
EN

Stack Overflow用户
提问于 2011-02-16 03:55:34
回答 14查看 297.7K关注 0票数 174

我需要一个函数,它将生成一个给定范围内的随机整数(包括边界值)。我没有不合理的质量/随机性要求,我有四个要求:

  • ,我需要它快一点。我的项目需要生成数百万(有时甚至数千万)的随机数,而我当前的生成器函数已被证明是一个瓶颈。
  • 我需要它相当统一(使用rand()就可以了)。
  • 最小-最大范围可以是<0,1>到<-32727,32727>。
  • 它必须是可播种的。

我目前有以下C++代码:

代码语言:javascript
复制
output = min + (rand() * (int)(max - min) / RAND_MAX)

问题是,它并不是真正一致的-只有当rand() = RAND_MAX (对于Visual C++,它是1/32727)时才返回max。对于像<-1,1>这样的小范围来说,这是一个主要问题,在这些小范围中,最后一个值几乎永远不会返回。

所以我拿起纸和笔,想出了以下公式(它建立在(int)(n + 0.5)整数舍入技巧的基础上):

但它仍然不能给我均匀的分布。重复运行10000个样本,我得到的值为-1,0的比率为37:50:13。1.

你能推荐更好的配方吗?(甚至是整个伪随机数生成器函数)

EN

回答 14

Stack Overflow用户

回答已采纳

发布于 2011-02-16 04:16:19

一个比您的更快,但仍然不是很均匀的分布式解决方案是

代码语言:javascript
复制
output = min + (rand() % static_cast<int>(max - min + 1))

除非范围的大小是2的幂,否则此方法会生成 numbers,而不考虑rand()的质量。要全面测试此方法的质量,请访问read this

票数 110
EN

Stack Overflow用户

发布于 2013-11-01 22:08:03

最简单的(因此也是最好的) C++ (使用2011标准)答案是

代码语言:javascript
复制
#include <random>

std::random_device rd;     // only used once to initialise (seed) engine
std::mt19937 rng(rd());    // random-number engine used (Mersenne-Twister in this case)
std::uniform_int_distribution<int> uni(min,max); // guaranteed unbiased

auto random_integer = uni(rng);

不需要重新发明轮子。不需要担心偏见。不需要担心使用时间作为随机种子。

票数 325
EN

Stack Overflow用户

发布于 2011-02-27 05:14:35

如果您的编译器支持C++0x,并且您可以选择使用它,那么新的标准<random>头可能会满足您的需求。它有一个高质量的uniform_int_distribution,可以接受最小和最大界限(根据需要包括在内),您可以在各种随机数生成器中进行选择以插入到该分布中。

这是生成一百万个均匀分布在-57,365中的随机int的代码。我已经使用了新的std <chrono>工具对其进行计时,正如您提到的那样,性能是您最关心的问题。

代码语言:javascript
复制
#include <iostream>
#include <random>
#include <chrono>

int main()
{
    typedef std::chrono::high_resolution_clock Clock;
    typedef std::chrono::duration<double> sec;
    Clock::time_point t0 = Clock::now();
    const int N = 10000000;
    typedef std::minstd_rand G;                // Select the engine
    G g;                                       // Construct the engine
    typedef std::uniform_int_distribution<> D; // Select the distribution
    D d(-57, 365);                             // Construct the distribution
    int c = 0;
    for (int i = 0; i < N; ++i) 
        c += d(g);                             // Generate a random number
    Clock::time_point t1 = Clock::now();
    std::cout << N/sec(t1-t0).count() << " random numbers per second.\n";
    return c;
}

对于我(2.8 GHz英特尔酷睿i5),这将打印出来:

每秒2.10268e+07随机数。

您可以通过将int传递给生成器的构造函数来设定生成器的种子:

代码语言:javascript
复制
    G g(seed);

如果您后来发现int没有覆盖您的发行版所需的范围,可以通过如下方式更改uniform_int_distribution来补救(例如,更改为long long):

代码语言:javascript
复制
    typedef std::uniform_int_distribution<long long> D;

如果您后来发现minstd_rand不是一个足够高质量的生成器,也可以很容易地将其替换掉。例如:

代码语言:javascript
复制
    typedef std::mt19937 G;  // Now using mersenne_twister_engine

对随机数生成器有单独的控制,并且随机分布可以相当自由。

我还计算(未显示)该分布的前4个“矩”(使用minstd_rand),并将它们与theoretical values进行比较,试图量化该分布的质量:

代码语言:javascript
复制
min = -57
max = 365
mean = 154.131
x_mean = 154
var = 14931.9
x_var = 14910.7
skew = -0.00197375
x_skew = 0
kurtosis = -1.20129
x_kurtosis = -1.20001

( x_前缀指的是“期望的”)

票数 61
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5008804

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档