我想使用C ++快速连续生成许多随机数序列。我面临的问题是使用我的代码获得相同的序列。考虑以下从U [0,1]
生成变量的玩具示例#include <iostream>
#include <cstdlib>
#include <ctime>
#include <fstream>
using namespace std;
// function to generate uniform random
// variates on [0,1]
void uniform(double *pt, int n);
int main()
{
// File to output results
ofstream output("output.txt");
// Generate two sequences of uniform random variates
double uniform_variates1[10];
double *pt_uniform1 = uniform_variates1;
uniform(pt_uniform1, 10);
double uniform_variates2[10];
double *pt_uniform2 = uniform_variates2;
uniform(pt_uniform2, 10);
// Output results
for( int i=0; i < 10; i++)
{
output << uniform_variates1[i] << "\t" << uniform_variates2[i] << endl;
}
return 0;
}
void uniform(double *pt, int n)
{
// seed for rand()
srand((unsigned)time(0));
for( int i=0; i < n; i++)
{
pt[i] = 1.0*rand()/RAND_MAX;
}
}
此代码的示例输出,表示所有其他运行如下所示。
0.0769677 0.0769677
0.933256 0.933256
0.234535 0.234535
0.413251 0.413251
0.0505387 0.0505387
0.854274 0.854274
0.0886563 0.0886563
0.57152 0.57152
0.697195 0.697195
0.7004 0.7004
可以看出,这两个序列完全相同。我该如何避免这个问题?我需要为项目做类似的事情,除了我需要大约1000个独特的随机数序列。
答案 0 :(得分:3)
你需要了解PRNG是如何工作的,而提示是在 Pseudo 的P中(其余是随机数生成器)。
PRNG不会创建随机的数字序列,因为它不是随机的:对于相同的输入(种子),始终会生成相同的序列,并且此序列在给定的时间段内循环。例如,公共32 bits Mersenne Twiser的周期为2 19932 -1个元素,这意味着它会在多次迭代后循环。当然,还有其他有趣的属性,例如生成速度或随机性&#34;观察,我建议你阅读这篇文章。
最重要的是,PRNG完全依赖于它的种子;因此,只要你给它相同的种子,它将返回相同的数字序列。在您的情况下,C库使用由srand
播种的单个(隐藏和未指定)PRNG,并通过rand
迭代其序列。你观察到的问题是由于你用来为这个PRNG种子的time
函数缺乏精确性:因为它只在第二个时精确,如果你在同一秒内绘制N系列,你将获得所有N相同。这可以通过更好的播种来解决:在过程开始时只播种一次。
注意:几年前使用time(0)
作为种子的一些pocker服务器被黑客入侵,因为time
的输出几乎不是秘密;为了保密PRNG是不够的,你需要CSPRNG,这是密码安全的PRNG。
现在,还有一个问题,不幸的是,使用全局状态会在口中留下不良状态(并发问题和所有......)因此建议使用C ++ 11 <random>
库,如果你有权访问它。在C ++ 11中,有3个部分可以生成随机数:
std::random_device
使用实现定义的熵源来为引擎播种std::default_random_engine
)生成随机值注意:引擎和分发都是(可能)有状态的,应该通过引用传递。
例如你可以这样做:
std::vector<double> uniform(std::default_random_engine& engine, size_t length) {
std::uniform_real_distribution<> dist(0, 1);
std::vector<double> result;
for (size_t i = 0; i != length; ++i) {
result.push_back(dist(engine));
}
return result;
}
并在main
中调用此函数,该函数的任务是播种引擎:
int main()
{
static size_t const Size = 10;
// File to output results
std::ofstream output("output.txt");
// Initialize the engine
std::random_device rd;
std::default_random_engine engine(rd());
// Generate two sequences of uniform random variates
std::vector<double> const u1 = uniform(engine, Size);
std::vector<double> const u2 = uniform(engine, Size);
// Output results
for (size_t i = 0; i < Size; i++)
{
output << u1[i] << "\t" << u2[i] << "\n";
}
return 0;
}