gpt4 book ai didi

ruby - Ruby 兰特的有效种子范围是多少?

转载 作者:数据小太阳 更新时间:2023-10-29 06:53:27 25 4
gpt4 key购买 nike

Ruby 将 PRNG 实现为“修改后的 Mersenne Twister,周期为 2**19937-1”。 1

我对 MT 的理解是它在 2^32 种不同的种子上运行。让我感到困惑的是 Random.new(seed) 接受任意大的数字,例如 Random.new(2**100)

但是,我无法找到(逻辑上的)碰撞:

Random.new(1).rand(10**5) == Random.new(2**32-1).rand(10**5) => false
Random.new(1).rand(10**5) == Random.new(2**32).rand(10**5) => false
Random.new(1).rand(10**5) == Random.new(2**32+1).rand(10**5) => false

鉴于我们希望利用 MT 的最大种子范围,即我们希望使用尽可能多的不同种子,同时仍然避免与两个不同种子发生碰撞,那么什么种子范围可以实现这一点?

我尝试了解 Ruby 的随机实现中发生了什么,但没有深入了解。 https://github.com/ruby/ruby/blob/c5e08b764eb342538884b383f0e6428b6faf214b/random.c#L370

最佳答案

Mersenne Twister 序列为 2 ** ( 624 * 32 - 1 ) - 1 长,种子值用于设置 PRNG 的内部状态,该状态与内部位置直接相关那个顺序。

最容易找到的重复似乎是每个 2 ** ( 624 * 32 ),并且可以像这样工作:

 repeat_every =  2 ** ( 624 * 32 )

start_value = 5024214421 # Try any value

r1 = Random.new( start_value )

r2 = Random.new( start_value + repeat_every )

r17 = Random.new( start_value + 17 * repeat_every )

r23 = Random.new( start_value + 23 * repeat_every )

r1.rand == r2.rand
# true

r17.rand == r23.rand
# true

或者试试这个:

 repeat_every =  2 ** ( 624 * 32 )

start_value = 5024214421 # Try any value

r1 = Random.new( start_value )

r2 = Random.new( start_value + repeat_every )

Array.new(10) { r1.rand(100) }
# => [84, 86, 8, 58, 5, 21, 79, 10, 17, 50]

Array.new(10) { r2.rand(100) }
# => [84, 86, 8, 58, 5, 21, 79, 10, 17, 50]

重复值与 Mersenne Twister 的工作原理有关。 MT 的内部状态是一个由 624 个 32 位无符号整数组成的数组。您链接的 Ruby 源代码将 Ruby Fixnum 打包到一个数组中 - 神奇的命令是

  rb_integer_pack( seed, buf, len, sizeof(uint32_t), 0,
INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_NATIVE_BYTE_ORDER );

然而,这不是一件容易玩的东西,它在 internal.h 中定义,因此只有在使用 Ruby 解释器本身时才能真正访问它。您不能从普通的 C 扩展中访问此函数。

压缩整数然后通过函数 init_by_array 加载到 MT 的内部状态。这是一个看起来相当复杂的函数——打包的种子值并没有直接写入状态,而是逐项生成状态,添加提供的数组值,使用各种异或、加法和交叉引用以前的值(这里的 Ruby 源代码也添加了打包数组的索引位置,注释为“非线性”,我认为这是对标准 MT 的引用修改之一)

请注意,MT 序列的大小小于 2 ** ( 624 * 32 ) - 我在这里显示的 repeat_every 值一次跳过 2 个序列,但最容易找到重复的种子值,因为很容易看出它如何将内部状态设置为完全相同(因为种子的数组表示中的前 624 项是相同的,这就是稍后使用的所有内容)。其他种子值也会产生相同的内部状态,但这种关系是一个复杂的映射,它将 19938 位空间中的每个整数与另一个为 MT 创建相同状态的整数配对。

关于ruby - Ruby 兰特的有效种子范围是多少?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20076394/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com