2013-12-17 69 views
17

我对c和C++相对陌生。在我用来编程的语言java中,它很容易实现随机数生成。只需从名为Math的类中调用静态随机方法即可。随机数字生成器 - 为什么每次都要种子

int face = ((int)(Math.random() * 6) + 1); 

C和C++,你必须“种子随机数生成器”,通过调用函数srand功能模拟一个骰子掷...

srand (time(NULL)); 

这么做的意义是什么 - 我的意思是说,每次运行代码时都必须为随机数生成器生成种子?

+14

注意:您不应该在每次运行特定代码时播种它;你应该在每次过程开始时播下它。 –

+1

@RogerLipscombe这实际上取决于你想达到的目标。 – juanchopanza

+0

[wikipedia](http://en.wikipedia.org/wiki/Pseudorandom_number_generator)文章相当不错。在Java中,它仍然在第一次调用时种下PRNG,但是它[底层。](http://docs.oracle.com/javase/6/docs/api/java/lang/Math.html#random() ) – kbshimmyo

回答

10

如果您没有为生成器生成种子,每次运行程序时都会有相同的种子,并且随机数序列每次都是相同的。

另请注意,您只应在程序开始时播种一次发生器。

8

优点是您可以通过提供相同的种子重复一个随机数字序列。

游戏精英使用它来存储整个世界,由数以千计的明星组成,作为单个数字。 为了第二次生成完全相同的世界,刚刚提供了相同的种子。

+4

这对于调试涉及随机数生成的代码非常有用。 – kbshimmyo

+0

确实。如果你想要的主要是不可预测的种子,但是能够复制你观察到的行为,请让程序显示/记录与结果一起使用的种子。并添加一个命令行开关来指定种子,使用它来代替'time(NULL)'(如果存在)。 – Medinoc

+0

这对模拟也很方便。 – joshin4colours

4

伪随机数发生器需要种子来生成不同的随机数序列(不总是)。如果你不想重复的序列,那么你需要种子伪随机数发生器。

试试这些代码,看看有什么不同。
没有种子:

#include <stdio.h> 
#include <stdlib.h> 

int main() 
{ 
     printf("%d", rand()%6 + 1); 
} 

种子:

#include <stdio.h> 
#include <stdlib.h> 
#include <time.h> 

int main() 
{ 
     srand(time(NULL)); 
     printf("%d", rand()%6 + 1); 
} 
25

由于相同的种子,伪随机数生成器,每次都会产生相同的序列。所以这取决于您是否每次运行时都需要不同的伪随机数序列。

这真的取决于您的需求。有时候你想重复一个序列。而当你不这样做的时候。您需要了解每个特定应用程序的需求。

你绝对不能做的一件事是在生成单个序列的过程中重复种子。这样做很可能会破坏序列的分布。

+0

种子是什么意思?我搜索谷歌和大多数链接没有解释它。 –

+2

@Borat http://en.m.wikipedia.org/wiki/Random_seed –

+0

“你永远不可能做的一件事就是在生成单个序列的过程中重复种子,这样做很可能会破坏序列的分布。”你能解释为什么吗?在我看来,每次播种都会让它更“随意”。 – Jose

12

通常所说的随机数发生器实际上是一个伪随机号码发生器。这通常意味着,如果您为该序列提供“密钥”(称为“种子”),则可以生成相同的随机序列。当您希望测试基于随机化的算法时,这非常有用,并且您需要确保可重复的结果。

如果您没有“种子”您的随机数字发生器,它会默认使用某些(通常基于系统时间)随机数播种,因此每次运行程序时都会产生不同的序列。

1

在C/C++,一个骰子将模拟这样的:

int face = (rand() % 6) + 1); 
       ^
        |___________ Modulo operator 

% 6通过5限制了随机数来0和+ 1被制成偏移极限,所以变得1至6

+0

在OP中提到java中的Math.random(),它返回一个介于0之间的浮点数。0和1.0。 –

+2

@KlasLindbäck感谢您的澄清。我编辑了我的答案。我也知道,在C/C++中也没有'Math.random()'。 –

1

随机数发生器并不是真正的随机数:假设你用12种子并制作100个随机数,重复该过程并再次用12种子并再制作100个随机数,它们将是相同的。

我已经在20个条目各12的种子来说明附2点运行的一个小样本,产生它的代码之后立即:

#include <iostream> 
#include <cstdlib> 

using namespace std; 

int main() 
{ 
    srand(12); 
    for (int i =0;i<100; i++) 
    { 
     cout << rand() << endl; 
    } 
    return 0; 
} 

two randomly generated sequences both seeded with 12

为了避免这样的重复它因为时间总是在变化,并且两个程序在同一时间产生随机序列的几率很小(尤其是在毫秒级时),所以人们可以合理安全地使用时间作为一个几乎独特的种子。

要求:播种只需要发生一次每个独特的随机序列,你需要生成。

但是,如果知道确切时间何时生成第一个序列,则存在意想不到的上/下端: 然后通过输入种子值可以重新生成确切的序列手动操作,导致随机数生成器以与之前相同的方式逐步完成其过程(这是存储随机序列的一个好处,也是保存它们随机性的一个缺点)。