“重置”伪随机数生成器种子多次?

时间:2012-12-08 16:34:30

标签: random

今天,我的朋友想到了使用生成的伪随机数多次设置伪随机数生成器的种子以“使事情更随机化”。

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. 对随机性没有任何作用(即既不增加也不减少)?
  4. 伪随机数生成器的任何专家都能给出一些详细的解释,以便我可以说服我的朋友吗?我很乐意看到答案解释一些伪随机数生成器算法的进一步细节。

3 个答案:

答案 0 :(得分:5)

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

  1. 没有特殊关联保证的意外数字。此级别的生成器通常具有一些隐藏的相关性,这些相关性可能对您很重要,或者可能不重要。
  2. 具有已知非相关性的统计独立数字。这些通常是数值模拟所必需的。
  3. 以密码方式保护无法猜到的数字。当出现安全问题时,始终需要这些。
  4. 这些都是确定性的。随机数生成器是一种具有某种内部状态的算法。应用该算法一次产生新的内部状态和输出数。播种发电机意味着建立内部状态;种子界面并不总是允许设置每个可能的内部状态。作为一个好的经验法则,总是假设默认库random()例程仅在最弱的级别1级运行。

    要回答您的具体问题,问题(1)中的算法不能增加随机性,(2)可能会减少它。因此,随机性的期望严格低于在开始时播种一次。原因在于可能存在短迭代周期。函数F的迭代循环是一对整数nk,其中F^(n) (k) = k,其中指数是F的应用次数。例如,F^(3) (x) = F(F(F(x)))。如果有一个短的迭代周期,随机数将比其他情况更频繁地重复。在提供的代码中,迭代函数是为生成器播种,然后获取第一个输出。

    要回答一个你不太了解的问题,但这与了解这一点有关,用毫秒计数器进行播种会使你的发电机无法通过3级测试,不可测试。这是因为可能的毫秒数加密小,这是一个已知可以进行穷举搜索的数字。在撰写本文时,2 ^ 50应该被认为是加密小的。 (对于任何年份的加密大小,请找一位有信誉的专家。)现在一个世纪的毫秒数大约是2 ^(41.5),因此出于安全考虑,不要依赖这种形式的播种。

答案 1 :(得分:1)

您的示例不会增加随机性,因为entropy没有增加。它只是从程序的执行时间派生而来。

计算机不是使用基于当前时间的东西,而是维护一个熵池,并使用统计上随机(或至少是不可能的)的数据来构建它。例如,网络数据包之间的定时延迟,或键击,或硬盘驱动器读取时间。

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

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

答案 2 :(得分: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对象与任何其他Random对象一样。它只需要你花费更多的时间来创建它。