在什么情况下你想为你的随机数生成器设置不同的种子?

时间:2016-10-19 16:12:16

标签: java random probability

我想知道在什么情况下你想为你的随机数发生器设置不同的种子。我看到代码在某个地方人们每次需要时创建一个PUBSUB <subcommand> ... args ... 对象,并且看到人们有时会将它作为一个实例变量,在构造对象时使用单个种子。例如

Random

// same seed
class A {
    private Random random;
    public A() { random = new Random(); }
    public int nextInt() { return random.nextInt(10000); }
    public double nextDouble() { return random.nextDouble(); }
}

请忽略这两个包装类的设计,只是试图显示差异。

3 个答案:

答案 0 :(得分:7)

重复使用Random的两个理由:

  • 创建Random

  • 会产生开销
  • 如果代码是 fast ,则创建两个不同的Random对象可能最终使用相同的种子值,即结果不是随机的。即使代码 ,但不同的Random对象将使用密切相关的种子值播种,从而降低随机因素。

拥有多个Random实例的一个原因,虽然不是每次使用时创建新实例的原因。引用javadoc

  

java.util.Random的实例是线程安全的。但是,跨线程同时使用相同的java.util.Random实例可能会遇到争用并因此导致性能不佳。请考虑在多线程设计中使用ThreadLocalRandom

即使在单线程应用程序中,使用ThreadLocalRandom也可能是合适的,这是获取共享Random实例的简单方法。

答案 1 :(得分:6)

随机数生成器,例如java.util.Random,生成由初始种子表征的确定性数字序列。制作这样的发生器以产生在整个PRNG范围内随机且(通常)均匀变化的序列。

如果您使用相同的种子,则会得到相同的数字序列。在某些情况下这可能很有用,但通常是不可取的。特别是,如果您在生成每个数字之前使用相同的种子为PRNG播种,那么您的数字将不会出现任何随机性。

但是,即使您在生成每个数字之前使用不同的种子为PRNG播种,也会出现更微妙的问题,包括如果您实例化新的Random而不是重用现有的Random。在这种情况下,您不能保证具有相同的结果范围或分布,并且您的结果可能会显示出仅在您播种一次时不会显示的相关性。

所以,当你说

  

我想知道你在什么情况下想要为你的随机数生成器设置不同的种子。

,关于我想要在你的计划的一次运行中想要改变种子的唯一原因是你已经从PRNG发布了足够的抽奖,你担心某人决定其实施和内部状态,因此能够预测后续数字。只有在相当特殊的情况下,这才是实践中的一个问题。

另一方面,您通常希望每次运行程序时选择不同的种子,否则每次都会生成相同的随机数序列。

通常,您应该为您的PRNG播种一次,然后根据需要使用它,而不需要重新播种。使用多个独立的PRNG并不一定是错的,但这样做的原因大多是组织的(例如,不必担心同步,不必提供注入Private Sub Label5_MouseClick(sender As Object, e As MouseEventArgs) Handles Label5.MouseClick If e.Button = MouseButtons.Left Then SawWhetOwl.Text = (Val(SawWhetOwl.Text) + 1).ToString() Label5.Text = SawWhetOwl.Text ElseIf e.Button = MouseButtons.Right Then If SawWhetOwl.Text = CInt(SawWhetOwl.Text < 0) Then Exit Sub Else SawWhetOwl.Text = (Val(SawWhetOwl.Text) - 1).ToString() Label5.Text = SawWhetOwl.Text End If End If End Sub 实例)而不是功能。

答案 2 :(得分:0)

如果你真的只想要一个单一的值,只有一次,在一个应用程序中,那么任何方法都会产生足够相似的结果,并不重要。如果您要抽取大量随机数,特别是重复运行的相同算法,通过重复使用相同的Random对象,您将获得更好(不是更快,但更好)的结果。

拥有一个对两个对象的原因是因为你需要截然不同的随机数序列(可能,你的种子不同,想要控制不同)。这是一个依赖于应用程序的答案,以确定它是否重要。

对于大多数用途,您需要默认种子,但为应用程序提供使用预定义种子运行的选项非常有用;例如:

  if (seedInputValueProvided)
    mRandom = new Random(seedInputValue);
  else
    mRandom = new Random();

为什么这样?测试。发展。如果您只创建一个随机对象并使用已知的种子值重新使用它,则可以重新运行特定方案以重复测试同一事物(或重新创建问题)。