每次使用RNG时都要种下RNG好主意吗?

时间:2011-09-06 13:37:51

标签: c++ algorithm random

我正在使用Mersenne twister算法来洗牌。每次甲板需要洗牌时,我会用时间(NULL)+ deckCutCardNumber播种它,这是用户选择切割牌组的地方。我只是在第一手接种它并继续用相同的种子生成它们或者这种方法更随机的时候会得到更好的结果吗?

由于

7 个答案:

答案 0 :(得分:5)

只播放PRNG 一次。生成的序列的统计特性仅在种子之后得到保证。如果每次重新设置,结果序列可能没有任何可预测的统计属性。

例如,考虑一个PRNG,它总是将种子值本身作为序列中的第一个数字返回,但在其范围内是完全一致的。只要您不使用第一个数字,这就构成了一个伟大的PRNG。但是,如果你在每次使用之前重新设置它,比如递增计数器值,你就没有随机性了!

答案 1 :(得分:4)

假设用户没有弄乱时钟(或者仔细减少他们的切割数量已经过去的时间),他们永远不会看到PRNG的重复状态,所以它没有太大的区别你做什么。您将从任何种子值[*]中获得Mersenne Twister的合理分配,并在重新播种后以任何可行的步骤进行分配。

但是,如果你渴望重新种植,你可以通过播种时间加上用户选择的数字加上在播种前从发生器获得的输出来结合两种方法。它将PRNG的当前状态(部分而非全部)与新种子数据结合起来,因此在某种程度上所有过去时间和削减值(以及PRNG的使用次数)都会影响状态,而不仅仅是最近的。以这种方式将更多信息投入到种子价值中可以被认为比涉及更少信息且因此可信值更少的种子“更随机”。

关于Mersenne Twister的唯一特别之处在于,如果你可以观察它的600多个输出,那么你可以推断出它的内部状态并预测输出的其余部分,直到重新接种为止。再说一次,你可能不会将MT用于那种重要的应用程序:如果你以任何方式依赖于重新设置,那么你应该首先使用更安全的PRNG。显然,如果用户可以预测出PRNG的值,那么对您的应用程序来说无关紧要,因为用户和您一样知道时间。所有这一切都告诉你,它的播种方式并不重要,只要它没有播种完全相同的值,以便两个游戏是相同的。因此,它是否也被重新接种并不重要。

[*]这并非严格地说,MT有一些弱种子。但只要你在播种时考虑到这一点(例如,在使用之前对种子进行哈希处理,以便不可能偶然发现坏值),你可以解决这个问题。

答案 2 :(得分:1)

它既不是随机的,也不是随机的。无论如何,它根本不是随机的,但如果你每次都重新播种,你就不会注意到任何差异。

但是,我建议反对它,因为time返回一个unsigned int,所以如果你在同一秒内调用它两次,你将获得相同的数字,因此RNG中的数字相同。然后是分布和所有这些。

答案 3 :(得分:1)

如果你每次播种用户选择的种子比只播种一次,那么随机性就会降低。原因是切割的选择可能会有一个偏差的分布(可能在第10张牌上切割最有可能等)。如果你想连续播种,你应该使用系统时间作为种子。

答案 4 :(得分:1)

是的,每次不播种时,你会得到更好的效果。这是(好的)随机数发生器的目的。

在这种特殊情况下,第一个值只会在你在洗牌之间等待时增加,而连续应用的rng会在你的整个范围内给出数字。

答案 5 :(得分:1)

我建议为每个shuffle初始化PRNG,原因完全不同:它允许你仅使用种子量化甲板的状态,这意味着你可以向用户提供种子,或者记录它,或者其他什么适合,并能够轻松地重建后期处理的手。

你真的应该根据时间避免播种 - 通常更好的方法是使用/dev/urandom之类的随机源。

编辑:如果您担心玩家猜测内部状态并因此知道将来会处理哪些牌,则会出现另一个重播的理由。在观察到Mersenne Twister的624个输出后(至少根据维基百科),这是可能的;只有重复使用相同的PRNG才能实现这一点。但是,如果这确实很重要,那么你肯定不应该根据时间进行播种,而且你应该使用加密安全的PRNG。

答案 6 :(得分:0)

重新播种随机数发生器不会给你提供任何质量更高的随机数而不是播种一次(在很多情况下,根据你的种子值,相反)。