2012-12-08 135 views
2

今天,我的朋友有一个想法,设置使用产生“使事情变得更加随机”的伪随机数的伪随机数生成器多次的种子。“重置”伪随机数发生器种子多次?

在C#中的一个例子:

// Initiate one with a time-based seed 
Random rand = new Random(milliseconds_since_unix_epoch()); 
// Then loop for a_number_of_times... 
for (int i = 0; i < a_number_of_times; i++) 
{ 
    // ... to initiate with the next random number generated 
    rand = new Random(rand.Next()); 
} 
// So is `rand` now really random? 
assert(rand.Next() is really_random); 

但我在想,这大概可以增加获得正在使用的伪随机数生成器的重复种子的机会。

  1. 会让事情变得更加随机,
  2. 进行循环,通过使用一定数量的种子,或
  3. 无助于随机性(即既不增加也不减少)?

伪随机数发生器的任何专家能给出一些详细的解释,以便说服我的朋友吗?我很乐意在某些伪随机数生成器算法中看到解释更多细节的答案。

+0

ou ...你最好的选择是(xkcd)掷骰一次,并简单地使用它作为一个常数。 Nahw只是开玩笑 - 计算机不能使随机数字非常好。每个非伪随机都使用外部(如物理测量)源来进行初始化和随机...因此,对于正常的随机数在应用程序中使用其他任何类似time.h(正如您已经这样做)这样的麻烦是不值得的。如果你真的需要随机数,考虑使用硬件 – Najzero

+0

@Najzero嗯,只是想了解更多关于伪数字发生器的知识,所以我不会为此得到一个核衰变检测器。 :) –

+0

ffffshhh ...没有承诺更多,一切或http://xkcd.com/221/ – Najzero

回答

5

有使用的伪随机数三个基本层次。每个级别都包含在它下面的一个级别。

  1. 意外的数字,没有特别的相关性担保。这个级别的生成器通常会有一些对您而言可能很重要或者可能不重要的隐藏关联。
  2. 具有已知非相关性的统计独立数。这些通常是数值模拟所必需的。
  3. 密码安全的数字,不能被猜测。当安全问题时,这些都是必需的。

这些都是确定性的。随机数发生器是一种具有某种内部状态的算法。一旦应用算法产生新的内部状态和输出数字。播种发电机意味着建立一个内部状态;种子界面并不总是允许设置每个可能的内部状态。作为一个好的经验法则,总是假定默认库random()例程仅在最弱的级别1上运行。

要回答您的特定问题,问题(1)中的算法不能增加随机性, (2)可能会减少它。因此,随机性的期望严格低于一开始播种一次。原因来自短迭代周期的可能存在。为函数F迭代周期是一对整数nk其中F^(n) (k) = k,其中指数是被施加的次数F数目。例如,F^(3) (x) = F(F(F(x)))。如果迭代周期较短,那么随机数字会比其他情况下的频繁重复。在所提供的代码中,迭代函数是对发生器进行种子处理,然后获取第一个输出。

要回答一个问题,你没有听问,但它是有关获得这方面的一个理解,用毫秒计数器播种,使您的发电机故障3级,unguessability的考验。这是因为可能的毫秒数是加密小,这是一个已知的数量受到穷尽搜索。在撰写本文时,2^50应该被认为是密码小的。 (因为任何年份的密码都很大,请找一位有信誉的专家。)现在,一个世纪的毫秒数大约是2 ^(41.5),所以不要为了安全目的而依靠这种播种形式。因为在entropy没有增加

0

这不会使事情变得更加“随机”。

我们的种子确定rand.next()为我们提供了数字的随机寻找,但完全确定顺序。

反而使事情变得更随机的,你的代码定义一个映射,从您最初的种子到一些最后的种子,并给予相同的初始种子,你将永远结束了相同的最终的种子。

尝试使用此代码玩,你会明白我的意思(也here is a link to a version you can run in your browser):

int my_seed = 100; // change my seed to whatever you want 
Random rand = new Random(my_seed); 
for (int i = 0; i < a_number_of_times; i++) 
{ 
    rand = new Random(rand.Next()); 
} 
// does this print the same number every run if we don't change the starting seed? 
Console.WriteLine(rand.Next()); // yes, it does 

这个最终种子的Random对象,就像任何其他的随机对象。它只是需要更多的时间来创建它。

+0

又是如何使用当前的任何时间更少(如'milliseconds_since_unix_epoch()')? –

+0

是的,使用'milliseconds_since_unix_epoch()'是生成你的初始种子的正确方法。在你的代码中,最终的随机对象将有一个种子,它是这个初始种子的可预测转换。我提供的代码的目的是向您展示,通过执行这种可预测的转换,您不会再向系统中引入更多的熵。 –

1

你的榜样,不会增加随机性。它只是从程序的执行时间导出的。

而不是使用基于当前时间的东西,电脑维护熵池,并与统计学随机的(或至少,不可猜测)是数据建立起来。例如,网络数据包之间的时间延迟或击键,或硬盘读取时间。

如果你想得到好的随机数,你应该进入熵池。这些被称为Cryptographically secure pseudorandom number generators

在C#中,请参阅Cryptography.RandomNumberGenerator Class以获取安全随机数的正确方法。