为什么我总是用rand()得到相同的随机数序列?
这是我第一次尝试随机数与C(我错过了C#)。 这是我的代码:
int i, j = 0; for(i = 0; i <= 10; i++) { j = rand(); printf("j = %d\n", j); }
使用这段代码,我每次运行代码时都会得到相同的序列。 但是如果我在for
循环之前添加srand(/*somevalue/*)
,它会产生不同的随机序列。 谁能解释为什么?
你必须种下它。 随着时间的推移是一个好主意:
srand()
#include <stdio.h> #include <stdlib.h> #include <time.h> int main () { srand ( time(NULL) ); printf ("Random Number: %d\n", rand() %100); return 0; }
你得到相同的序列,因为如果你不调用srand(),rand()会自动被赋值为1。
编辑
由于评论
rand()
将返回一个介于0和RAND_MAX
之间的数字(在标准库中定义)。 使用模运算符( %
)给出除法rand()/100
的其余部分。 这将强制随机数在0-99范围内。 例如,要获得0-999范围内的随机数,我们将应用rand()%1000
。
rand()返回伪随机数。 它根据给定的algorithm生成数字。 该algorithm的起点总是相同的,所以你会看到每个调用产生相同的序列。 这在您需要validation程序的行为和一致性时非常方便。
你可以用srand函数设置随机发生器的“种子”(在程序中只调用srand一次)从rand()生成器获得不同序列的一种常见方法是将种子设置为当前时间或者过程:
函数srand(时间(NULL)); 或者srand(getpid()); 在节目的开始。
对于一台计算机来说,生成真正的随机性是非常困难的,但是对于实际的非encryption相关工作,试图平均分配生成的序列的algorithm工作正常。
从男人兰德引用:
srand()函数将其参数设置为由rand()返回的新随机整数序列的种子。 通过使用相同的种子值调用srand()可以重复这些序列。
如果没有提供种子值,则rand()函数自动以1的值进行播种。
所以,在没有种子值的情况下,rand()假定种子为1(在你的情况下每次)并且具有相同的种子值,rand()将产生相同的数字序列。
如果我还记得Knuth在“随机数生成”一章开头的开创性工作“计算机程序devise艺术”的引用,它是这样的:
“从技术上讲,任何试图用math方法产生随机数的人都处于犯罪状态。
简而言之,股票随机数发生器是algorithm,math和100%可预测的。 在许多情况下,这实际上是一件好事情,例如对于某些统计练习来说,需要可重复的“随机”数字序列,例如某些统计练习中,您不希望“摆动”集群效应。
尽pipe从计算机硬件中获取“随机”数据是一种stream行的第二种select,但它并不是真正的随机性 – 尽pipe操作环境越复杂,随机性的可能性也越大,或者至less是不可预测性。
真正的随机数据发生器倾向于寻求外部来源。 放射性衰变和类星体的行为一样是最受欢迎的。 任何根源于量子效应的东西都是随机的 – 这对爱因斯坦的烦恼很重要。
这里有很多答案,但似乎没有人真正解释过为什么rand()总是在给定相同种子的情况下生成相同的序列 – 甚至种子实际上在做什么。 所以在这里。
rand()函数维护一个内部状态。 从概念上讲,你可以把它看作一个叫做rand_state的全局variables。 每次你调用rand(),它都会做两件事情。 它使用现有的状态来计算一个新的状态,并且它使用新的状态来计算一个数字来返回给你:
state_t rand_state = INITIAL_STATE; state_t calculate_next_state(state_t s); int calculate_return_value(state_t s); int rand(void) { rand_state = calculate_next_state(rand_state); return calculate_return_value(rand_state); }
现在你可以看到,每次调用rand()时,都会使rand_state沿着预定的path移动一步。 你所看到的随机值只是基于你在那条路上的位置,所以他们也会按照预定的顺序。
现在这里是srand()进来的地方。它可以让你跳到path上的不同点:
state_t generate_random_state(unsigned int seed); void srand(unsigned int seed) { rand_state = generate_random_state(seed); }
state_t,calculate_next_state(),calculate_return_value()和generate_random_state()的具体细节可能因平台而异,但它们通常很简单。
从这里可以看出,每当程序启动时,rand_state将从INITIAL_STATE(相当于generate_random_state(1))开始 – 这就是为什么在不使用srand()的情况下总会得到相同的序列。
随机数发生器实际上不是随机的,他们像大多数软件是完全可预测的。 兰特所做的是在每次调用时创build一个不同的伪随机数字一个似乎是随机的。 为了正确使用它,你需要给它一个不同的起点。
#include <stdio.h> #include <stdlib.h> #include <time.h> int main () { /* initialize random seed: */ srand ( time(NULL) ); printf("random number %d\n",rand()); printf("random number %d\n",rand()); printf("random number %d\n",rand()); printf("random number %d\n",rand()); return 0; }
这是从http://www.acm.uiuc.edu/webmonkeys/book/c_guide/2.13.html#rand :
宣言:
void srand(unsigned int seed);
这个函数给函数rand使用的随机数发生器播种。 用相同的种子播种srand将导致rand返回相同的伪随机数序列。 如果srand没有被调用,rand就像srand(1)被调用一样。
rand()返回一个序列中的下一个(伪)随机数。 发生什么事情是每次运行时都有相同的系列(默认为“1”)。 要开始一个新的系列,在开始调用rand()之前,必须先调用srand()。
如果你每次都想要随机的东西,你可以试试:
srand (time (0));
在调用rand()
之前调用srand(sameSeed)
rand()
。 更多细节在这里 。
播种rand()
void srand (unsigned int seed)
该函数将种子build立为新的一系列伪随机数的种子。 如果在使用srandbuild立种子之前调用rand,则使用值1作为默认种子。
为了在每次运行程序时生成不同的伪随机序列,请执行srand(time(0))
没有人会回答他的问题。
与此代码我得到相同的sequance每次代码,但它会生成随机序列,如果我在for循环之前添加srand(/ somevalue /)。 有人可以解释为什么?
从我的教授告诉我,如果你想确保你的代码正常运行,看看是否有什么问题,或者你可以改变什么,就可以使用它。
顺便说一句:rand不是随机的(PRNG = PSEUDO Random Number Generator,其中pseudo是关键字!)可能非常有用。
如果在networking上的计算机上使用相同的algorithm,并且使用“随机”数字计算一些数据(例如游戏状态),并且如果所有机器上的代码被同步,使得兰德呼叫在相同地点/所有客户端的时间,那么你可以通过重新生成数据/事件/本地任何东西来减lessnetworking负载。
伪随机是一件可爱的事情。 🙂
PS如果你依赖rand(om)被同步,那么你应该编码你自己的实现 – 否则平台和其他的差异会破坏你的乐趣。 🙂