【问题标题】:What's the difference between a random number generator's seed and state?随机数生成器种子和状态有什么区别?
【发布时间】:2017-08-17 19:41:52
【问题描述】:

我看到一个 C++ 程序接受种子和状态来设置 std::default_random_engine,这是 std::linear_congruential_engine 的 typedef(至少在我的系统上)。 seed() 方法用于设置初始种子,operator>> 用于状态。

我知道播种随机数生成器 (RNG) 的原理,但使用它可以与它的状态互换。

【问题讨论】:

  • Seed == 起始值以生成基础(生成初始状态)。 State == 表示生成器当前所在的位置。
  • 对于线性同余随机引擎,种子确实是引擎的第一个状态(因为引擎本身是一个整数),但是对于例如mersenne twister 引擎(在标准中),状态是整数序列,而种子是单个值,第一个状态是使用种子计算的。

标签: c++ random


【解决方案1】:

种子是用来初始化生成器的值,状态是每次调用生成随机数后生成器的当前状态。对于非常简单的随机数生成器,例如线性同余的随机数生成器,种子和状态是相同的(或者至少,存储在相同的变量中),但它们当然不必是。

【讨论】:

  • 通过“起始值”,这不是生成的第一个数字,而是一种指定要生成的随机数序列/模式的方式。
  • 后续小问题:设置状态时,初始种子对后续生成的随机数会失去作用,对吗?
  • @jdoe 这完全取决于 RNG 的实现——RNG 完全有可能(并且可能很有用,如果没有别的原因,用于调试)会记住它的初始种子。
【解决方案2】:

如果您(重新)播种 PRNG,从而(重新)初始化它,则将其当前状态替换为新的状态,这是种子的(可能是微不足道的)功能。为了减轻输入中的模式,这个初始函数通常更复杂地分配熵到所有状态。

operator>> 恢复内部状态使用了这样一个简单的映射。

无论哪个(重新)播种最后完成是有效的,其余的只是浪费努力。

【讨论】:

    【解决方案3】:

    免责声明:我不是随机数生成器理论方面的专家,以下大部分内容实际上来自 C++ 标准本身。

    生成器的状态 Xi,是生成器的实际内部状态——你需要生成的(最少的)信息生成器的下一个状态和下一个值:

    • 您使用“转换”函数从一种状态转换到另一种状态,Xi+1 = TA(Xi);
    • 您使用“生成”函数GA(Xi)生成一个值。

    种子S是一个“值”,用于生成第一个状态X0。 p>

    生成器的状态是它固有的(见下文),同一个生成器的两个实现将具有相同的状态(在理论上),但可能需要完全不同的种子。

    在 C++ 中,您使用单个值作为 Mersenne Twister 引擎的种子,而它的状态是整数序列...我可以选择实现一个只能通过整数序列作为种子的 Mersenne Twister 引擎(这将成为第一个状态)。


    标准随机库中的一些示例以便更好地理解:

    线性同余生成器只是一个遵循以下递归关系的生成器:

    X i+1 = TA(Xi) = (a . Xi + c) mod m强>

    其中acm 是生成器的参数。在这种情况下:

    • 引擎的状态就是Xi的当前值;
    • 种子是X0的值;

    ...当您使用值 k 为生成器播种时,实际上您只需设置 Xi = k

    但还有其他生成器,例如在 C++11 标准随机库中,您会找到 Mersenne Twister (MT) 生成器。

    我当然不是 Mersenne Twister 发电机方面的专家,但从c++ draft,你可以看到:

    • MT生成器的状态实际上是一个整数序列Xi = (Xi,0, Xi, 1子>, ...);
    • MT 的种子(在标准中)实际上是一个值;

    ...当您使用值 k 为生成器播种时,您实际上执行“复杂”操作1 来计算 X0 sub> 来自 k,但 X0 肯定不是 k

    1这些操作我就不赘述了,因为我也不是很了解,不过大家可以看看standard看看状态(序列)是怎样的从种子生成。

    【讨论】:

      【解决方案4】:

      通常,种子值用于生成随机数。通常出于性能原因,种子值用于生成一组数字,然后将其添加到数组或内存表中。进一步调用获取随机数只需从表中读取预先生成的值。表中的当前索引和表中的当前值集可以被认为是状态。当使用可以利用大量随机数调用的复杂系统(例如游戏引擎)时,调试(重现错误)变得非常困难,除非您可以重现“随机”事件。如果您保存然后恢复“状态”和种子值,您可以确保代码运行时每次都会选择相同的“随机”数字。我确信这只是众多可能的答案之一,但希望对您有所帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-08-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-06-17
        • 1970-01-01
        相关资源
        最近更新 更多