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

pet*_*ter 5 java random probability

我想知道你在什么情况下想要为你的随机数发生器设置不同的种子.我看到代码在某个地方人们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(); }
}
Run Code Online (Sandbox Code Playgroud)

// different seed is used every time when you call the method
class B {
    public int nextInt() { return new Random().nextInt(10000); }
    public double nextDouble() { return new Random().nextDouble(); }
}
Run Code Online (Sandbox Code Playgroud)

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

And*_*eas 7

重用的两个理由Random:

  • 创建一个开销有一个开销Random.

  • 如果代码很快,创建两个不同的Random对象可能最终使用相同的种子值,即结果不是随机的.即使代码不那么快,Random也会使用密切相关的种子值播种不同的对象,从而减少随机因素.

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

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

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


Joh*_*ger 6

随机数发生器,例如java.util.Random,产生的特征在于初始种子数的确定性序列.制造这样的发生器以产生看起来在PRNG的整个范围内随机且(通常)均匀变化的序列.

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

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

所以,当你说的时候

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

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

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

一般来说,你应该为你的PRNG播种一次,然后根据需要使用它,而不需要重新播种.使用多个独立的PRNG并不一定是错的,但这样做的原因主要是组织(例如,不必担心同步,不必提供注入Random实例)而不是功能.