C++ srand(time(NULL)) 产生类似的结果

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6668282/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 20:30:06  来源:igfitidea点击:

srand(time(NULL)) generating similar results

c++visual-studiovisual-studio-2010random

提问by hyperknot

I don't understand why srand() generates so similar random numbers between runs!

我不明白为什么 srand()在运行之间生成如此相似的随机数

I am trying to run the following code

我正在尝试运行以下代码

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

However instead of a proper random number I always end up with almost the same number, which is growing slowly as the time goes. So I get numbers like: 11669, 11685, 11701, 11714, 11731.

然而,我总是得到几乎相同的数字,而不是一个适当的随机数,随着时间的推移,这个数字增长缓慢。所以我得到这样的数字:11669、11685、11701、11714、11731。

What am I doing wrong?

我究竟做错了什么?

I am using Visual Studio 2010 SP1.

我正在使用 Visual Studio 2010 SP1。

OK, is srand() really that simple? I mean how would anyone call it a random function?

好吧,srand() 真的那么简单吗?我的意思是怎么会有人称它为随机函数?

srand(1) => rand() = 41
srand(2) => rand() = 45
srand(3) => rand() = 48
srand(4) => rand() = 51
....

回答by James Kanze

First, srand()isn't a random function; it sets up the starting point of a pseudo-random sequence. And somewhat surprisingly, your implementation of rand()seems to be returning a value based on the previous state, and not on the newly calculated state, so that the first value after a call to srand()depends very much on the value passed to srand(). If you were to write:

首先,srand()不是随机函数;它设置了一个伪随机序列的起点。有点令人惊讶的是,您的 实现rand()似乎正在返回基于先前状态的值,而不是新计算的状态,因此调用后的第一个值在srand()很大程度上取决于传递给 的值 srand()。如果你要写:

srand( time( NULL ) );
rand();
std::cout << rand() << std::endl;

, I'm sure you'll see a lot more difference.

,我相信你会看到更多的不同。

FWIW: I tried the following on both Windows and Linux:

FWIW:我在 Windows 和 Linux 上都尝试了以下方法:

int
main()
{
    srand( time( NULL ) );
    int r1 = rand();
    std::cout << r1 << ' ' << rand() << std::endl;
    return 0;
}

Invoked 10 times at a one second interval, I got:

以一秒的间隔调用 10 次,我得到:

16391 14979
16394 25727
16397 3708
16404 25205
16407 3185
16410 13933
16417 2662
16420 13411
16427 2139

with VC++ under Windows—you'll note the very low variance of the first call to rand()—and

使用 Windows 下的 VC++——你会注意到第一次调用的差异非常小rand()——并且

1256800221 286343522
955907524 101665620
1731118607 991002476
1428701871 807009391
44395298 1688573463
817243457 1506183315
507034261 1310184381
1278902902 54648487
2049484769 942368151
1749966544 1833343137

with g++ under Windows; in this case, even the first value read is relatively random.

在 Windows 下使用 g++;在这种情况下,即使读取的第一个值也是相对随机的。

If you need a good random generator, you'll probably have to use one from Boost; the standard doesn't say much about what algorithm should be used, and implementations have varied enormously in quality.

如果你需要一个好的随机生成器,你可能不得不使用 Boost 中的一个;该标准并没有说明应该使用什么算法,并且实现的质量差异很大。

回答by Kyle

Make sure you're doing

确保你在做

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

and not

并不是

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

The first way the seed is changed every iteration. The second way you are performing the random function on a very similar seed each iteration (because time doesn't change much).

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

回答by Mark Ransom

If you are trying to run the program quickly in succession and get different random numbers each time, initializing with the current time is the wrong approach. What you need is a source of entropy; this questionmight get you started. Replacing time(NULL)with QueryPerformanceCounter()might be a good start, since it updates much more rapidly, but it's still somewhat predicatble - I don't know if that's important to you or not.

如果您试图连续快速运行程序并每次获得不同的随机数,则使用当前时间进行初始化是错误的方法。你需要的是一个熵源;这个问题可能会让你开始。替换time(NULL)withQueryPerformanceCounter()可能是一个好的开始,因为它更新得更快,但它仍然有些可预测 - 我不知道这对你是否重要。

回答by Cubbi

Since you have Visual Studio 2010, you can use the portable random device interfacefrom modern C++ instead of time() to seed srand():

由于您拥有 Visual Studio 2010,您可以使用现代 C++ 中的便携式随机设备接口而不是 time() 来种子 srand():

#include <iostream>
#include <random>
#include <cstdlib>
int main()
{
    std::random_device rd;
    std::srand(rd());
    std::cout << std::rand() << '\n';
}

Now running the program repeatedly will still produce different values. The same code will work with GNU g++ on Linux or any other modern compiler.

现在重复运行程序仍然会产生不同的值。相同的代码适用于 Linux 上的 GNU g++ 或任何其他现代编译器。

回答by hyperknot

OK, all credits go for Mark Ransom for his answer for explaining actually what is happening. I did not find source code in his linked question, so I googled it and found this, what is perfectly working on Windows. So for srand on windows, here is the source code to generate better srand() seed.

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

#include <windows.h>

int main()
{
  LARGE_INTEGER cicles;

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

  return 0;
}

回答by Fledi

I just had the same problem. The seeds were too similar even after tens of seconds. Since I get my numbers in this fashion:

我只是遇到了同样的问题。即使在几十秒后,种子也太相似了。由于我以这种方式获得我的数字:

int FlRandomInt(int LowerLimit, int UpperLimit)
{
 int Result;
 Result = rand();
 Result=LowerLimit+Result*(UpperLimit-LowerLimit)/RAND_MAX;

 return Result;
}

which I know is not the best way to go for integers, but I use the same procedure to generate random floats and doubles, so it's good to verify if those are significantly different, instead of just at the last decimals.

我知道这不是整数的最佳方法,但我使用相同的程序来生成随机浮点数和双精度数,因此最好验证它们是否有显着差异,而不仅仅是最后一位小数。

Anyway just wanted to post a solution that works fine for me. It's simply multiplying the time seed by 100:

无论如何只是想发布一个对我有用的解决方案。它只是将时间种子乘以 100:

srand(( unsigned )time( 0 ) * 100 );

Hope it helps, even if I'm sure there are more elegant ways around the problem.

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

回答by R.M.VIVEK Arni

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

}

回答by Clifford

From @James Kanze's test it seems that it is a peculiarity of VC++'s C runtime (though I am certain other libraries suffer in the same way). This library also suffers from having a minimum allowableRAND_MAX, but that's another issue.

从@James Kanze 的测试来看,它似乎是 VC++ 的 C 运行时的一个特性(尽管我确信其他库也有同样的问题)。这个库也受到最小允许RAND_MAX 的影响,但这是另一个问题。

The solution to the low variance of the initial value is simply to discard it:

初始值低方差的解决方案是简单地丢弃它:

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