2012-02-27 89 views
22

每次我运行一个程序rand()它给了我相同的结果。为什么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 

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

回答

33

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

如果调用函数srand(时间(NULL)),那么你会得到更多的随机结果:

的原因是,从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

您需要为随机数生成器生成种子(参见函数'srand')。假设你没有做密码学,那么用'时间'的输出进行播种可能就足够了。

11

如果您在未先致电srand()的情况下致电rand(),它将会如同隐式调用srand(1)那样操作。标准C99 7.20.2.2 The srand function(其上cstdlib基于)的相关位指出:

如果兰特被称为已作出函数srand任何呼叫之前,相同的序列应为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种可能性),输出的“随机”特性意味着它可能在此之前重复:-)

0

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

+1

Nit:数学上,这不会让他们“更随机”。 – 2012-02-27 10:51:11

+0

的确如此,但是在OP的问题中......(加上引号;-) – John3136 2012-02-27 23:48:41

2

这就是rand()功能的一个特点。

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

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

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

1

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

+1

'randomize'不是一个标准的C++函数。你在说哪个平台? – 2015-02-01 09:33:58

相关问题