【问题标题】:Does increasing RNG seed by 1 each time ensure not getting same consecutive values?每次将RNG种子增加1是否确保不会获得相同的连续值?
【发布时间】:2020-04-02 06:42:53
【问题描述】:

我有机会看到一些有趣的代码,它要么被用作愚人节玩笑(更新于 4 月 1 日公开),要么只是一个错误,因为有人不了解如何使用 RNG。

问题与作为 .NET/C# 一部分的 Random 类有关,但可能其他 RNG 的工作方式相同。

我找到的代码的简化版本,去掉所有不必要的细节后,看起来像这样:

for ( int i = startI; i < stopI; ++i ) {
    int newValue = new Random( i ).Next( 0, 3 ); // new RNG with seed i generates a single value from 3 options: 0, 1 and 2
    // rest of code
}

我确实在 LINQPad 中对该代码进行了简单的测试,以查看我在程序中观察到的是否只是我的“运气”,或者这是否真的是 RNG 以这种方式使用的方式。代码如下:

int lastChoice = -1;
int streakLength = -1;

for ( int i = 0; i < 100000000; ++i ) {
    int newChoice = new Random( i ).Next( 0, 3 );
    if ( newChoice == lastChoice ) {
        streakLength++;
        ( i + ";" + lastChoice + ";" + streakLength ).Dump();
    } else {
        lastChoice = newChoice;
        streakLength = 1;
    }
}

"The End".Dump();

Dump() 方法只是将值打印到屏幕上)

运行这个“脚本”的结果只是“The End”,仅此而已。这意味着,在生成随机值的 100M 周期中,当只有 3 个作为选项时,它没有一次能够生成相同的连续值

所以回到标题中的我的问题 - 是否在每次(整数)随机数生成之后将 RNG 的种子(特别是 .NET/C# 的 Random 类,但也欢迎一般答案)增加一个,以确保不会重复会出现连续值吗?或者这只是纯粹的运气?

【问题讨论】:

  • 更好的解决方案以及 Random 类的使用方式不是每次需要随机数时都创建一个新实例,而只是实例化一次并重用它。每次调用 Next 时,它的内部种子都会改变,以便后续调用 Next 将返回另一个数字。
  • @ckuri 这不是我应该如何使用它的问题,因为那不是我的代码,我没有维护它。我只对Random(或其他RNG)的内部结构感兴趣,这样使用它是否不会给我提供连续重复的值,因为这是我出人意料地观察到的。该代码的实际“目标”(除非这是我提到的一个笑话),是在某个时候给你 4 个连续重复的值,而我什至无法并排看到两个相同的数字。
  • Random 类的内部结构是,如果您不提供种子,它将使用当前时间作为种子。因此,在一个紧密的循环中,它会变得如此之快,以至于时钟不会改变,并且您将获得相同的种子和序列,如示例 1 所示。如果您提供的种子不是这种情况。 IIRC 该类使用 Mersenne Twister 算法,该算法的构建方式可以最大限度地减少不同种子的相同序列的机会。我认为有些种子会产生相同的序列,但是我不知道是否有连续的种子也适用。
  • 我不明白这个问题的重点。我得到了基本前提。但是,只有大约 40 亿个可能的种子值。为什么不让程序运行更长的时间(即比你已经至少运行一次的时间长 40 倍),然后你就会确定 PRNG 的一个特定实现会做什么?作为编程练习,并行化测试;只有 4 个内核,运行它的时间只需 10 倍(分区几乎完全独立……您只需要跟踪每个内核的第一个和最后一个结果,并将它们与相邻的结果进行比较分区)。
  • 如果由于某种原因你真的不想要一个简单的经验答案,你可以在这里看到自己的代码:referencesource.microsoft.com/#mscorlib/system/…(不,没有一般的答案......每个 PRNG会有自己的特点)

标签: c# random random-seed


【解决方案1】:

您显示的行为取决于 PRNG。

对于许多 PRNG,包括线性 PRNG,例如在 .NET Framework 的System.Random 中实现的那种,如果用连续种子初始化 PRNG 的两个实例,它们产生的数字序列可能相互关联,即使这些序列中的每一个都自己产生随机行为的数字。您在问题中描述的行为只是其中一种可能的结果。

特别是对于System.Random,这种现象在“A Primer on Repeatable Random Numbers”中有更详细的描述。

但是,其他 PRNG 为每个种子提供了自己独立的伪随机数序列(例如 SFC64 和基于计数器的 PRNG;例如,请参阅“并行随机数:像 1、2、3 一样简单”),还有一些PRNG 可以“超前”大量步骤来生成相互独立的伪随机数序列。

另见:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-04-03
    • 2017-12-29
    • 1970-01-01
    • 2021-09-27
    • 1970-01-01
    • 1970-01-01
    • 2017-01-24
    • 1970-01-01
    相关资源
    最近更新 更多