这是我第一次用C语言尝试随机数(我想念C#).这是我的代码:
int i, j = 0; for(i = 0; i <= 10; i++) { j = rand(); printf("j = %d\n", j); }
使用此代码,每次运行代码时都会得到相同的序列.但是如果我srand(/*somevalue/*)
在for
循环之前添加,它会生成不同的随机序列.有谁能解释为什么?
你必须播种它.随着时间播种它是一个好主意:
srand()
#include#include #include int main () { srand ( time(NULL) ); printf ("Random Number: %d\n", rand() %100); return 0; }
您获得相同的序列,因为rand()
如果您不调用,则自动播种值为1 srand()
.
由于评论
rand()
将返回介于0和RAND_MAX
(在标准库中定义)之间的数字.使用模运算符(%
)给出除法的余数rand() / 100
.这将强制随机数在0-99范围内.例如,要获得0-999范围内的随机数,我们将适用rand() % 1000
.
rand()返回伪随机数.它根据给定的算法生成数字.该算法的起点始终相同,因此您将看到为每次调用生成的相同序列.当您需要验证程序的行为和一致性时,这很方便.
您可以使用srand函数设置随机生成器的"种子" (仅在程序中调用一次srand)从rand()生成器获取不同序列的一种常用方法是将种子设置为当前时间或id过程:
函数srand(时间(NULL)); 或者srand(getpid()); 在计划开始时.
对于计算机来说,生成真正的随机性非常困难,但是对于实际的非加密相关工作,尝试均匀分布生成的序列的算法工作正常.
引用man rand:
srand()函数将其参数设置为rand()返回的新的伪随机整数序列的种子.通过使用相同的种子值调用srand(),可以重复这些序列.
如果未提供种子值,则rand()函数将自动播种,值为1.
因此,如果没有种子值,rand()
则将种子假定为1(每次在您的情况下)并使用相同的种子值,rand()
将生成相同的数字序列.
这里有很多答案,但似乎没有人真正解释为什么rand()总是在给定相同种子的情况下生成相同的序列 - 甚至是种子真正做的事情.所以这里.
rand()函数保持内部状态.从概念上讲,您可以将其视为某种类型的全局变量rand_state.每次调用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沿着预先确定的路径向前移动一步.您看到的随机值仅基于您沿着该路径的位置,因此它们也将遵循预先确定的顺序.
现在这里是srand()的用武之地.它可以让你跳到路径上的另一个点:
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(),总是得到相同的序列.
如果我记得Knuth在随机数生成章节开头的开创性着作"计算机编程艺术"的引用,它是这样的:
"从技术上讲,任何试图通过数学方法产生随机数的人都处于犯罪状态".
简单地说,股票随机数生成器是算法,数学和100%可预测.在许多情况下,这实际上是一件好事,其中需要可重复的"随机"数字序列 - 例如对于某些统计练习,您不希望结果中的"摆动"真正随机数据引入,这要归功于聚类效应.
虽然从计算机的硬件中获取"随机"数据是一种流行的第二种选择,但它并不是真正随机的 - 尽管操作环境越复杂,随机性的可能性就越大 - 或者至少是不可预测性.
真正随机的数据生成器倾向于寻找外部资源.放射性衰变是最受欢迎的,类星体的行为也是如此.任何根源于量子效应的东西都是随机的 - 这对爱因斯坦的烦恼很大.
随机数生成器实际上并不是随机的,它们像大多数软件一样是完全可预测的.rand做的是每次调用一个看起来是随机的伪随机数.为了正确使用它,你需要给它一个不同的起点.
#include#include #include 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; }