C++ 为什么 rand() 每次运行都会产生相同的数字序列?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9459035/
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-27 12:51:55  来源:igfitidea点击:

Why does rand() yield the same sequence of numbers on every run?

c++random

提问by Patrick Lorio

Every time I run a program with rand()it gives me the same results.

每次我用rand()它运行一个程序时,都会得到相同的结果。

Example:

例子:

#include <iostream>
#include <cstdlib>

using namespace std;

int random (int low, int high) {
    if (low > high)
        return high;
    return low + (rand() % (high - low + 1));
}

int main (int argc, char* argv []) {
    for (int i = 0; i < 5; i++)
        cout << random (2, 5) << endl;
}

Output:

输出:

3
5
4
2
3

Each time I run the program it outputs the same numbers every time. Is there a way around this?

每次我运行程序时,它每次都会输出相同的数字。有没有解决的办法?

回答by Robert Mason

The seed for the random number generator is not set.

未设置随机数生成器的种子。

If you call srand(time(NULL))then you will get more random results:

如果你打电话,srand(time(NULL))那么你会得到更多的随机结果:

#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

int main() {
    srand(time(NULL));
    cout << rand() << endl;
    return 0;
}

The reason is that a random number generated from the rand()function isn't actually random. It simply is a transformation. Wikipedia gives a better explanation of the meaning of pseudorandom number generator: deterministic random bit generator. Every time you call rand()it takes the seed and/or the last random number(s) generated (the C standard doesn't specify the algorithm used, though C++11 has facilities for specifying some popular algorithms), runs a mathematical operation on those numbers, and returns the result. So if the seed state is the same each time (as it is if you don't call srandwith a truly random number), then you will always get the same 'random' numbers out.

原因是从rand()函数生成的随机数实际上并不是随机的。这简直就是一种转变。维基百科对伪随机数生成器的含义给出了更好的解释:确定性随机位生成器。每次调用rand()它时都会使用生成的种子和/或最后一个随机数(C 标准没有指定使用的算法,尽管 C++11 有指定一些流行算法的工具),运行数学运算这些数字,并返回结果。因此,如果种子状态每次都相同(就像您不srand使用真正的随机数调用一样),那么您将始终得到相同的“随机”数。

If you want to know more, you can read the following:

如果您想了解更多,可以阅读以下内容:

http://www.dreamincode.net/forums/topic/24225-random-number-generation-102/

http://www.dreamincode.net/forums/topic/24225-random-number-generation-102/

http://www.dreamincode.net/forums/topic/29294-making-pseudo-random-number-generators-more-random/

http://www.dreamincode.net/forums/topic/29294-making-pseudo-random-number-generators-more-random/

回答by paxdiablo

If you call rand()without first calling srand(), it will act as if you have called srand(1)implicitly. The relevant bit of the standard C99 7.20.2.2 The srand function(on which cstdlibis based) states:

如果您在rand()没有先调用的情况下调用srand(),它将表现得好像您已经srand(1)隐式调用了一样。标准的相关部分C99 7.20.2.2 The srand functioncstdlib基于该标准)指出:

If rand is called before any calls to srand have been made, the same sequence shall be generated as when srand is first called with a seed value of 1.

如果在对 srand 进行任何调用之前调用 rand,则应生成与第一次调用 srand 时使用种子值为 1 时相同的序列。

In other words, you willget the same sequence each time. You can change your maininto:

换句话说,您每次都会得到相同的序列。您可以将您的更改main为:

int main (int argc, char* argv []) {
    srand (time (0));  // needs ctime header.
    for (int i = 0; i < 5; i++)
        cout << random (2, 5) << endl;
    wait ();
}

to fix this, assuming you don't run it more than once a second.

要解决此问题,假设您每秒运行它的次数不超过一次。

As mentioned, you'll need the ctimeheader for this. You should also be pulling in cstdlibsince that's where randand srandlive. It's also usually a good idea to use the cXXXheaders rather than the XXX.hones (cmathrather than math.h, for example).

如前所述,您需要ctime为此提供标题。你也应该拉进来,cstdlib因为那是那里randsrand住的地方。使用cXXX标头而不是标头XXX.hcmath而不是math.h,例如)通常也是一个好主意。

So, having made allthose changes (and using explicit namespaces, which I prefer though others may not), I'd end up with:

因此,在进行了所有这些更改后(并使用了显式命名空间,虽然其他人可能不会这样做,但我更喜欢),我最终会得到:

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <cmath>

void wait () {
    int e;
    std::cin >> e;
}

int random (int low, int high) {
    if (low > high) return high;
    return low + (std::rand() % (high - low + 1));
}

int main (int argc, char* argv []) {
    std::srand (std::time (0));
    for (int i = 0; i < 5; i++)
        std::cout << random (2, 5) << '\n';
    wait ();
}

which gives a different sequence each time I run it, for a few times anyway. Obviously, there's a hard limit on when the data will repeat (there are only 45possibilities) and the "random" nature of the output means it may repeat before then as well :-)

每次我运行它时都会给出不同的序列,无论如何几次。显然,数据何时重复存在硬性限制(只有 4 5 种可能性)并且输出的“随机”性质意味着它也可能在此之前重复:-)

回答by Sebastian Mach

That's a feature of the rand()function.

这是rand()函数的一个特点。

What you have is not a random number generator, but more strictly a "pseudorandom number generator". Being able to reproduce the same random sequences for the same seed (you seed using the srand(x)function) can be important to reproduce bugs or to preserve state across program runs.

您拥有的不是随机数生成器,而是更严格的“伪随机数生成器”。能够为同一个种子(您使用该srand(x)函数播种)重现相同的随机序列对于重现错误或在程序运行中保持状态非常重要。

Personally, I use this feature to be able to pause/persist rendering-processes in a Monte Carlo-based terrain renderer. A nice side effect is that you are able to guarantee different Monte Carlo experiments on different machines, and therefore be able to generate guaranteed different results that can then be reduced in a final step to a higher quality end result (of course you can later reuse this higher quality end result to produce even higher quality results).

就个人而言,我使用此功能能够在基于蒙特卡罗的地形渲染器中暂停/保持渲染过程。一个很好的副作用是你可以保证在不同的机器上进行不同的蒙特卡罗实验,因此能够生成有保证的不同结果,然后可以在最后一步减少到更高质量的最终结果(当然你以后可以重用这种更高质量的最终结果可以产生更高质量的结果)。

Note, however, that neither C nor C++ define the number sequence from rand(). So if you need guaranteed sequences across platforms, use one of C++11's new random number generators (e.g. a Mersenne Twister), roll your own (some generators are almost trivial to grasp, however, because most of them rely on specific overflow behaviour their implementation might not be trivial), or use a third-party component (e.g. boost::random).

但是请注意,C 和 C++ 都没有定义从rand(). 因此,如果您需要跨平台的有保证的序列,请使用 C++11 的新随机数生成器之一(例如Mersenne Twister),自己动手(然而,有些生成器几乎不难掌握,因为它们中的大多数依赖于特定的溢出行为它们的实现可能不是微不足道的),或者使用第三方组件(例如 boost::random)。

回答by Michael Kohne

You need to seed the random number generator (see the function 'srand'). Assuming you aren't doing cryptography, then seeding it with the output of 'time' is probably good enough.

您需要为随机数生成器设置种子(请参阅函数“srand”)。假设你没有做密码学,那么用“时间”的输出来播种它可能就足够了。

回答by John3136

You are actually getting psuedo random numbers. To make them "more random" you can seed the random number generator using something that "changes" (most commonly the current time).

你实际上得到的是伪随机数。为了使它们“更随机”,您可以使用“改变”的东西(最常见的是当前时间)来为随机数生成器提供种子。

回答by Smatik

Use randomize(). It automatically seeds the value. Or if you want to use rand() then you can seed it by using srand(seedvalue); the seed value can be anything like system time...that'll give you different random numbers every time.

使用随机化()。它会自动为该值设定种子。或者如果你想使用 rand() 那么你可以使用 srand(seedvalue); 种子值可以是系统时间之类的任何东西......每次都会给你不同的随机数。