srand(time(NULL)) 产生类似的结果[重复]

Posted

技术标签:

【中文标题】srand(time(NULL)) 产生类似的结果[重复]【英文标题】:srand(time(NULL)) generating similar results [duplicate] 【发布时间】:2011-07-12 17:18:31 【问题描述】:

我不明白为什么 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
....

【问题讨论】:

每次拨打rand()时你都在播种吗?只需播种一次! 你用当前时间初始化,想知道为什么它会慢慢增加? 我到处读到它是在 C++ 应用程序中初始化 srand 的正确方法。我每个 main() 只做一次。 从字里行间看,我猜你的程序只产生一个数字,而你正在多次运行它——对吗? 是的,srand 使用类似的种子启动它时产生类似的结果是完全正常的。 【参考方案1】:

首先,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++;在这种情况下,即使读取的第一个值也是 比较随机。

如果您需要一个好的随机生成器,您可能必须使用一个 来自升压;该标准并没有太多说明应该是什么算法 使用,并且实现的质量差异很大。

【讨论】:

大约五年前,我在我们产品的 Windows 版本的生产代码中遇到了这个问题。解决方案是在播种后吃掉第一个 rand() 调用,仅适用于 Windows。我对 Windows、AIX 和 Linux 进行了广泛的分析(数十亿个样本),并在所有三个测试环境中得到了可接受的相似结果。我还花时间使用了更好的种子值(以毫秒为单位的当前时间 % 32000 + 进程的 pid,类似的东西)。【参考方案2】:

确保你在做

srand ( time(NULL) );
while(condition) 
    int x = rand();
    cout << x << endl;

而不是

while(condition) 
    srand ( time(NULL) );
    int x = rand();
    cout << x << endl;

每次迭代都会改变种子的第一种方式。第二种方法是在每次迭代时对非常相似的种子执行随机函数(因为时间变化不大)。

【讨论】:

后者之所以行不通是因为当前时间更新的不够频繁,所以很多次迭代会读取相同的时间,因此使用相同的种子。 我就是这样做的。 int main(int argc, char* argv[]) srand ( time(NULL) ); ..... 该代码不会打印出多个结果。您给了我们一系列数字,但您显示的唯一代码打印出一个数字。此外,理论上的while 可能只是程序的多次运行。【参考方案3】:

如果你想连续快速运行程序,每次得到不同的随机数,用当前时间初始化是错误的做法。你需要的是熵的来源; this question 可能会让您入门。将 time(NULL) 替换为 QueryPerformanceCounter() 可能是一个好的开始,因为它更新得更快,但它仍然有些可预测 - 我不知道这对你是否重要。

【讨论】:

很高兴知道QueryPerformanceCounter()播种 @Kyle,不幸的是 QueryPerformanceCounter 仅适用于 Windows。 Linux 使用 /dev/random 有一个更好的解决方案,尽管它涉及打开和关闭文件。 @Mark time 似乎是最好的便携式解决方案,但大多数系统都有很多不同的值可以使用。很长一段时间,我习惯使用time的hash,进程id和机器IP地址,这样两个人同时启动程序仍然会得到完全不同的序列。 (当然/dev/random更好,也是我今天在Unix下使用的。) 我在这里使用 QueryPerformanceCounter() 做了一个 sn-p:pastebin.com/DGxZZuRN【参考方案4】:

由于您拥有 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++ 或任何其他现代编译器。

【讨论】:

酷,这是我的新作品。它是当前标准的一部分,还是 C++0x 扩展? @Mark Ransom 它是 TR1 扩展的一部分,包含在 C++0x 中【参考方案5】:

好的,Mark Ransom 的所有功劳都归功于他解释实际发生的事情的答案。我在他的链接问题中没有找到源代码,所以我用谷歌搜索了它,发现这个在 Windows 上完美运行。因此,对于 windows 上的 srand,这里是生成更好的 srand() 种子的源代码。

#include <windows.h>

int main()

  LARGE_INTEGER cicles;

  QueryPerformanceCounter(&cicles);
  srand (cicles.QuadPart);

  return 0;

【讨论】:

【参考方案6】:

我也遇到了同样的问题。即使在几十秒之后,这些种子也太相似了。因为我以这种方式得到我的号码:

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

希望它有所帮助,即使我确信有更优雅的方法来解决这个问题。

【讨论】:

调用一个虚拟 rand();在 srand() 之后;使其更加独特。或者使用我回答中的代码:***.com/questions/6668282/…【参考方案7】:

从@James Kanze 的测试看来,这似乎是 VC++ 的 C 运行时的一个特性(尽管我确信其他库也会受到同样的影响)。这个库也有minimum allowableRAND_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;

【讨论】:

【参考方案8】:
#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();


【讨论】:

以上是关于srand(time(NULL)) 产生类似的结果[重复]的主要内容,如果未能解决你的问题,请参考以下文章

c语言哪个时间函数是精确到毫秒的?使用srand(time(NULL))的话,如果在同一秒运行程序

08.随机数的产生

C++产生随机数

time.h中time(NULL),stdlib.h中srand(), rand()

C语言编程小tip

C++产生随机数