当前位置:  开发笔记 > 编程语言 > 正文

为什么我总是使用rand()得到相同的随机数序列?

如何解决《为什么我总是使用rand()得到相同的随机数序列?》经验,为你挑选了6个好方法。

这是我第一次用C语言尝试随机数(我想念C#).这是我的代码:

int i, j = 0;
for(i = 0; i <= 10; i++) {
    j = rand();
    printf("j = %d\n", j);
}

使用此代码,每次运行代码时都会得到相同的序列.但是如果我srand(/*somevalue/*)for循环之前添加,它会生成不同的随机序列.有谁能解释为什么?



1> kjfletch..:

你必须播种它.随着时间播种它是一个好主意:

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()根本不是一个坏主意,无论你如何种下它.除了PRNG算法的未知强度之外,它通常只需要32位种子,因此即使您不通过播种时间使其变得非常容易,强暴也是合理的.播种兰德()与安全的熵源就像给驴类固醇并在[肯塔基]德比中输入.
如果安全性是一个问题,那么随着时间的推移将其播种是一个相当糟糕的主意,因为攻击者通常可以相对容易地找到或猜测启动时间(在几十到几百次尝试中),然后重放您的伪随机数序列.如果可能,请尝试使用操作系统提供的种子熵源代替.
因为如果你不手动播种,那么它总是***默认接种为1.请参阅Aditya的回答.

2> nos..:

rand()返回伪随机数.它根据给定的算法生成数字.该算法的起点始终相同,因此您将看到为每次调用生成的相同序列.当您需要验证程序的行为和一致性时,这很方便.

您可以使用srand函数设置随机生成器的"种子" (仅在程序中调用一次srand)从rand()生成器获取不同序列的一种常用方法是将种子设置为当前时间或id过程:

函数srand(时间(NULL)); 或者srand(getpid()); 在计划开始时.

对于计算机来说,生成真正的随机性非常困难,但是对于实际的非加密相关工作,尝试均匀分布生成的序列的算法工作正常.


+1,特别是提到它对加密需求没有好处.
+1,提到它实际上是一个伪随机数生成器,这就是为什么总是给出具有相同起始种子值的相同数字.

3> Aditya Sehga..:

引用man rand:

srand()函数将其参数设置为rand()返回的新的伪随机整数序列的种子.通过使用相同的种子值调用srand(),可以重复这些序列.

如果未提供种子值,则rand()函数将自动播种,值为1.

因此,如果没有种子值,rand()则将种子假定为1(每次在您的情况下)并使用相同的种子值,rand()将生成相同的数字序列.



4> caf..:

这里有很多答案,但似乎没有人真正解释为什么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(),总是得到相同的序列.



5> 小智..:

如果我记得Knuth在随机数生成章节开头的开创性着作"计算机编程艺术"的引用,它是这样的:

"从技术上讲,任何试图通过数学方法产生随机数的人都处于犯罪状态".

简单地说,股票随机数生成器是算法,数学和100%可预测.在许多情况下,这实际上是一件好事,其中需要可重复的"随机"数字序列 - 例如对于某些统计练习,您不希望结果中的"摆动"真正随机数据引入,这要归功于聚类效应.

虽然从计算机的硬件中获取"随机"数据是一种流行的第二种选择,但它并不是真正随机的 - 尽管操作环境越复杂,随机性的可能性就越大 - 或者至少是不可预测性.

真正随机的数据生成器倾向于寻找外部资源.放射性衰变是最受欢迎的,类星体的行为也是如此.任何根源于量子效应的东西都是随机的 - 这对爱因斯坦的烦恼很大.



6> Howard May..:

随机数生成器实际上并不是随机的,它们像大多数软件一样是完全可预测的.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;
}

推荐阅读
牛尾巴2010
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有