我不明白为什么srand()会在运行之间生成如此相似的随机数
我正在尝试运行以下代码
srand ( time(NULL) );
int x = rand();
cout << x << endl;
然而,不是一个正确的随机数,我总是得到几乎相同的数字,随着时间的推移,这个数字正在缓慢增长。所以我得到的数字如:11669,11685,11701,11714,11731。
我做错了什么?
我正在使用Visual Studio 2010 SP1。
好的,srand()真的那么简单吗?我的意思是如何将其称为随机函数?
srand(1) => rand() = 41
srand(2) => rand() = 45
srand(3) => rand() = 48
srand(4) => rand() = 51
....
答案 0 :(得分:9)
首先,srand()
不是随机函数;它设定了起点
一个伪随机序列。有点令人惊讶的是,你的
rand()
的实现似乎正在返回一个基于的值
以前的状态,而不是新计算的状态,所以第一个
调用srand()
后的值很大程度上取决于传递给的值
srand()
。如果你要写:
srand( time( NULL ) );
rand();
std::cout << rand() << std::endl;
,我相信你会看到更多的不同。
FWIW:我在Windows和Linux上都试过以下内容:
int
main()
{
srand( time( NULL ) );
int r1 = rand();
std::cout << r1 << ' ' << rand() << std::endl;
return 0;
}
每隔一秒钟调用10次,我得到了:
16391 14979
16394 25727
16397 3708
16404 25205
16407 3185
16410 13933
16417 2662
16420 13411
16427 2139
在Windows下使用VC ++ - 你会注意到它的非常低的方差
先致电rand()
- 和
1256800221 286343522
955907524 101665620
1731118607 991002476
1428701871 807009391
44395298 1688573463
817243457 1506183315
507034261 1310184381
1278902902 54648487
2049484769 942368151
1749966544 1833343137
在Windows下使用g ++;在这种情况下,即使读取的第一个值也是如此 相对随意。
如果你需要一个好的随机发生器,你可能不得不使用一个 来自Boost;标准没有说明应该是什么算法 使用,实施的质量差异很大。
答案 1 :(得分:7)
确保你正在做
srand ( time(NULL) );
while(condition) {
int x = rand();
cout << x << endl;
}
而不是
while(condition) {
srand ( time(NULL) );
int x = rand();
cout << x << endl;
}
每次迭代都会更改种子的第一种方式。第二种方法是在每次迭代时对非常相似的种子执行随机函数(因为时间变化不大)。
答案 2 :(得分:3)
如果您尝试连续快速运行程序并且每次都获得不同的随机数,则使用当前时间初始化是错误的方法。你需要的是熵的来源; this question可能会让你开始。用time(NULL)
替换QueryPerformanceCounter()
可能是一个好的开始,因为它更新得更快,但它仍然有些可预测 - 我不知道这对你是否重要。
答案 3 :(得分:3)
由于您拥有Visual Studio 2010,因此您可以使用现代C ++中的可移植random device interface而不是time()来播种srand():
#include <iostream>
#include <random>
#include <cstdlib>
int main()
{
std::random_device rd;
std::srand(rd());
std::cout << std::rand() << '\n';
}
现在重复运行程序仍会产生不同的值。相同的代码适用于Linux或任何其他现代编译器上的GNU g ++。
答案 4 :(得分:1)
好的,Mark Ransom的所有学分都用于解释实际发生的事情。我没有在他的链接问题中找到源代码,所以我用Google搜索并找到了这个,在Windows上完美运行的是什么。所以对于Windows上的srand,这里是生成更好的srand()种子的源代码。
#include <windows.h>
int main()
{
LARGE_INTEGER cicles;
QueryPerformanceCounter(&cicles);
srand (cicles.QuadPart);
return 0;
}
答案 5 :(得分:1)
我遇到了同样的问题。几十秒后,种子太相似了。因为我以这种方式得到我的数字:
int FlRandomInt(int LowerLimit, int UpperLimit)
{
int Result;
Result = rand();
Result=LowerLimit+Result*(UpperLimit-LowerLimit)/RAND_MAX;
return Result;
}
我知道这不是整数的最佳方法,但我使用相同的程序生成随机浮点数和双精度数,因此最好验证它们是否有明显不同,而不是仅仅是最后一个小数。
无论如何只想发布一个适合我的解决方案。它只是将时间种子乘以100:
srand(( unsigned )time( 0 ) * 100 );
希望它有所帮助,即使我确定有更优雅的方法解决问题。
答案 6 :(得分:0)
从@James Kanze的测试来看,它似乎是VC ++的C运行时的特性(尽管我确信其他库也以同样的方式受到影响)。该库也有minimum allowable RAND_MAX,但这是另一个问题。
初始值的低方差的解决方案只是丢弃它:
void seed_rand( unsigned int seed )
{
srand( seed ) ;
(void)rand() ;
}
int main()
{
seed_rand( time( NULL ) );
int r1 = rand();
std::cout << r1 << ' ' << rand() << std::endl;
return 0;
}
答案 7 :(得分:0)
#include"stdio.h" //rmv coding for randam number access using c++
#include"conio.h"
#include"time.h"
void main()
{
time_t t;
int i;
srand(time(null));
for(i=1;i<=10;i++)
cout<<(unsigned)rand()%100-90<<"\t";
for(i=1;i<=10;i++)
cout<<(char)rand()%100-90<<"\t";
getch();
}