在编写Java程序时,我们setSeed
在Random
类中使用。我们为什么要使用这种方法?
我们不能只使用Random
而不使用setSeed
吗?使用的主要目的是setSeed
什么?
这样做的一个用途是它使您能够在将来重现您的程序的结果。
例如,我想为数据库中的每一行计算一个随机变量。我希望程序是可重现的,但我希望行之间的随机性。为此,我将随机数种子设置为每一行的主键。这样,当我再次运行程序时,我得到了相同的结果,但是在行之间,随机变量是伪随机的。
一个特定的种子总是会给出相同的“伪随机”数字序列。所以只有 2^48 个不同的序列,Random
因为setSeed
只使用了 48 位的seed
参数!此外setSeed
,还可以使用带有种子的构造函数(例如new Random(seed)
)。
当setSeed(seed)
或new Random(seed)
不使用时,Random()
构造函数将随机数生成器的种子设置为一个很可能与此构造函数的任何其他调用不同的值。
以上信息的Java参考:https ://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Random.html
在一般情况下,不要使用种子。只需使用空构造函数Random()
,不要调用setSeed
. 这样,每次构造和调用类时,您可能会得到不同的伪随机数。
对于需要重复相同伪随机数的数据相关调试,请使用特定种子。在这种情况下,请使用Random(seed)
或setSeed(seed)
。
对于非安全关键用途,无需担心是否可以识别特定种子/序列并预测后续数字,因为种子范围很大。但是,“java.util.Random 的实例在密码学上并不安全。考虑改为使用SecureRandom
获得密码学安全的伪随机数生成器,以供对安全敏感的应用程序使用。” 资源
种子用于初始化随机数生成器。种子用于设置生成一系列随机数的起点。种子将生成器设置为随机起点。一个唯一的种子返回一个唯一的随机数序列。
这可能会有所帮助。
伪随机数生成器 (PRNG),也称为确定性随机位生成器 DRBG,是一种用于生成近似随机数属性的数字序列的算法。该序列不是真正随机的,因为它完全由一组相对较小的初始值决定,称为 PRNG 的状态,其中包括一个真正的随机种子。
我可以看到这样做的两个原因:
您可以创建可重现的随机流。nextX
对于给定的种子,对(相同)方法的连续调用将返回相同的结果。
如果使用相同的种子创建 Random 的两个实例,并且为每个实例进行相同的方法调用序列,它们将生成并返回相同的数字序列
出于某种原因,您觉得您的种子质量高于默认来源(我猜它源自您 PC 上的当前时间)。
其他几个人提到了可重复性。可重现性是调试的核心,您需要能够重现错误发生的情况。
可重复性的另一个重要用途是您可以玩一些统计游戏来减少某些估计的可变性。见维基百科的方差减少文章更多细节,但直觉如下。假设您正在考虑银行或杂货店的两种不同布局。您无法同时构建它们并查看哪个效果更好,因此您使用模拟。您从排队理论中知道,排队的大小和客户体验的延迟部分是由于布局,但也部分是由于到达时间、需求负载等的变化,因此您在两个模型中使用了随机性。如果您完全独立地运行模型,并发现布局 1 中的线条比布局 2 中的大,这可能是因为布局的原因,也可能是因为布局 1 碰巧获得了更多客户或要求更高的交易组合由于抽签的运气。然而,如果两个系统使用完全相同的一组客户,同时到达并具有相同的交易需求,那么这是一个“更公平”的比较。您观察到的差异更有可能是因为布局。您可以通过在两个系统中重现随机性来实现这一点 - 使用相同的种子并同步,以便在两个系统中将相同的随机数用于相同的目的。