【问题标题】:Is it okay to seed the randomizer more than once if done this way?如果这样做,可以多次播种随机发生器吗?
【发布时间】:2015-11-19 03:27:05
【问题描述】:

假设我有这个循环:

for (i=0; i < 100; i++)
{
    srand(time(NULL));
    printf("%d\n", rand());
}

如果我的机器相当快,它应该打印相同的数字 100 次。

但如果我这样修改:

for (i=0; i < 100; i++)
{
    srand(time(NULL) + rand());
    printf("%d\n", rand());
}

然后它应该打印 100 个不同的数字。我的问题是,像这样播种随机发生器有什么问题吗?效率呢?会不会显着降低效率?

一个附带问题,如果我在 main() 函数中播种一次随机数,是否也足以用于其他函数(即我不需要在另一个使用 rand() 的函数中再次播种)?

编辑

我可能需要使用这种方式是有原因的(当然,除非我不知道有更好的方式)。假设我有一个自定义库,其函数使用rand()。但是该函数不知道之前是否播种了随机化器。在这种情况下,我将srand(time(NULL) + rand()) 放入该函数中,以确保随机化器被播种,即使它之前没有播种。

例子:

int main()
{
    int i;

    srand(time(NULL));  // Seeded here, but the print_rand() function does not know it

    for (i=0; i < 100; i++)
    {
        print_rand();
    }

    return(0);
}


// Pretend this function is in a library
void print_rand()
{
    srand(time(NULL) + rand()); // No guarantee if seeding was done before, so doing it here

    printf("%d\n", rand());
}

编辑 2

我刚刚用 1000000 个循环对其进行了测试。播种一次需要0.024s,每次播种需要4.972s。所以我想如果它是一个大循环,它确实会显着降低性能。

【问题讨论】:

  • 对随机发生器播种一次应该足以满足大多数应用程序的需要。否则,无论如何您都应该研究其他(更专业的)随机发生器。
  • 如果你想要真正随机的东西,那么你不应该使用rand()/srand()。改用英特尔安全密钥(自 2006 年起在英特尔 CPU 上可用)。
  • 问题是为什么您想要多次播种。这就像在问:“我需要一座红色的房子。我的房子可以涂红 100 次而不是一次吗?”
  • 谢谢,现在清楚多了。我并不是要将它用于非常安全的事情。它仅适用于小型游戏等。请参阅编辑。
  • 您可以使用静态变量来记住您是否已经播种。静态 int 播种 = 0; if(!seed) { srand(...);播种=1; }

标签: c loops random random-seed


【解决方案1】:

多次播种 PRNG 通常是错误的。它确实不会增加 PRNG 的安全性,也不会使其更快(可能更慢!)

PRNG 只需播种一次

是的,在一个地方播种就足够了。另一个故事是,如果您有同一个 prng 的多个实例,但事实并非如此,那是 C 而不是 C++,而 rand() 是静态的。

这都是关于你想用随机数据做什么......

  • 加密的东西?忘记使用 rand()、srand() 和 time()
  • 随机化一些 游戏人工智能?应该没问题

【讨论】:

    【解决方案2】:

    别这样。

    播种一次。

    srand(time(NULL) + rand()); 重复使用会引入统计偏差。直观地说,这是由于两个影响:(i)srand(rand()) 将有效地忽略所有其他数字,这将增加方差;(ii)srand(time(NULL)) 将引入一个额外的加法常数,这将导致生成器中的模运算符为比它应该更频繁地调用。您甚至可能会影响生成器的周期性。

    为什么不测试呢?我预计平均值会大体上是正确的,但我想方差和更高的时刻将会消失。

    【讨论】:

    • 您对偏见的看法是正确的,但这只是因为 rand() 是一个线性 con。生成器。
    • 重新播种会产生偏差,但只要您只执行一次,就不会向种子添加偏移量。播种 PRNG 就是为其循环选择一个入口点,添加一个班次只会移动入口点。只要您不重新播种,无论您在哪里攀爬,产生的数字周期都是相同的。
    【解决方案3】:

    您似乎想改进rand 的输出。

    1. 您的方法不会这样做。由于您的代码很可能是已知的,因此任何人都可以看到您所做的事情,然后您的方法相当于只调用一次 srand。
    2. 即使不知道您的代码,只知道您使用了rand,在大多数系统上由它生成的数字也很容易预测。

    rand 仅适用于非常简单的情况,即某些东西在人类看来是随机的。就像一个简单的游戏。在这种情况下,拨打srand 一次就足够了。

    如果您确实希望生成随机(定义为“不可预测”)数字,则不应使用rand 或random。然后你需要对你的操作系统做一些研究,并寻找一个合适的库来生成随机数。

    回答问题。这样做应该不会有什么坏处。也许你会让可预测的数字更加可预测。也许有偏差的数字会稍微有偏差。人类(唯一可以被rand 愚弄的实体)可能仍然会认为它们足够随机。另一方面,你这样做没有任何收获,那何必浪费时间呢?

    【讨论】:

      猜你喜欢
      • 2017-11-30
      • 2010-11-01
      • 2016-07-22
      • 2010-09-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多