为什么rand()在每次运行时产生相同的数字序列?

时间:2012-02-27 01:35:04

标签: c++ random

每次我使用rand()运行程序时,它都会给我相同的结果。

示例:

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

输出:

3
5
4
2
3

每次运行程序时,每次都输出相同的数字。有办法解决这个问题吗?

7 个答案:

答案 0 :(得分:48)

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

如果您致电srand(time(NULL)),您将获得更多随机结果:

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

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

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

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

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/

答案 1 :(得分:15)

如果您在未先致电rand()的情况下致电srand(),则会表现得就像您已隐式调用srand(1)一样。标准C99 7.20.2.2 The srand functioncstdlib所基于的)的相关位指出:

  

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

换句话说,每次都会获得相同的序列。您可以将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 ();
}

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

如上所述,您需要ctime标头。您也应该加入cstdlib,因为randsrand就在那里。使用cXXX标题而不是XXX.h标题通常也是一个好主意(例如cmath而不是math.h)。

所以,在完成所有这些更改(并使用显式命名空间,我更喜欢其他人可能没有)之后,我最终得到了:

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

每次运行时都会给出不同的序列,无论如何都是这样。显然,数据重复的时间有一个严格的限制(只有4个 5 可能性),输出的“随机”性质意味着它可能在此之前重复: - )

答案 2 :(得分:3)

这是rand()功能的一个功能。

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

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

但请注意,C和C ++都没有定义rand()的数字序列。因此,如果您需要跨平台保证序列,请使用C ++ 11中的一个新的随机数生成器(例如mersenne twister),滚动您自己(有些生成器几乎无法掌握,但是,因为它们大多依赖于特定的溢出行为,它们的实现可能并不简单),或者使用第三方组件(例如boost :: random)。

答案 3 :(得分:1)

您需要为随机数生成器播种(请参阅函数'srand')。假设你没有进行加密,那么用'time'的输出来播种就足够了。

答案 4 :(得分:0)

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

答案 5 :(得分:0)

C++ 使用伪随机数生成器。从本质上讲,这意味着您的程序正在读取一长串预先确定的数字。当您重复运行您的程序时,它每次都会给出相同的数字,因为它每次都从该数字列表的开头读取。

您可以将程序设置为从列表中的第 n 个数字开始。您可以使用时间或温度或其他任何“随机”的东西。 (对于温度,您可以取温度的最后一位,也可以使用其后的小数位。)

答案 6 :(得分:-1)

使用randomize()。它自动播种价值。 或者如果你想使用rand(),那么你可以使用srand(seedvalue)来播种它;种子值可以是系统时间......每次都会给你不同的随机数