关于java:带种子的随机数

random number with seed

参考:链接文本

我不明白下面这句话,有人能给我举个例子吗?

如果使用相同的种子创建两个随机实例,并且为每个实例执行相同的方法调用序列,则它们将生成并返回相同的数字序列。


既然你要举个例子:

1
2
3
4
5
6
7
8
9
10
11
12
import java.util.Random;
public class RandomTest {
    public static void main(String[] s) {
        Random rnd1 = new Random(42);
        Random rnd2 = new Random(42);

        System.out.println(rnd1.nextInt(100)+" -"+rnd2.nextInt(100));
        System.out.println(rnd1.nextInt()+" -"+rnd2.nextInt());
        System.out.println(rnd1.nextDouble()+" -"+rnd2.nextDouble());
        System.out.println(rnd1.nextLong()+" -"+rnd2.nextLong());
    }
}

无论您使用多个EDCOX1,1个实例,无论运行什么平台,或使用什么Java版本,都将具有相同的输出:

1
2
3
4
30 - 30
234785527 - 234785527
0.6832234717598454 - 0.6832234717598454
5694868678511409995 - 5694868678511409995

随机生成器是确定性的。如果随机输入相同,并且随机使用相同的方法,返回到程序的伪随机数序列将相同,即使在不同的机器上运行不同的程序。

这就是为什么它是伪随机的-返回的数字在统计上表现得像随机数,除非它们可以可靠地预测。真正的随机数是不可预测的。


随机类基本上是一个伪随机数生成器(也称为确定性随机位生成器),它生成一个近似随机数属性的数字序列。它通常不是随机的,而是确定性的,因为它可以由生成器中的小随机状态(如seed决定)。由于具有确定性,如果两个生成器上的方法和种子序列相同,则可以生成相同的结果。


这些数字不是真正随机的,给定相同的起始条件(种子)和相同的操作序列,将生成相同的数字序列。这就是为什么使用基本随机类作为任何加密或安全相关代码的一部分不是一个好的IEA的原因,因为攻击者可能会找出正在生成的Sequence并预测未来的数字。

对于发出非确定性值的随机数生成器,请查看SecureRandom。

更多信息请参见维基百科上的随机数生成和计算方法。


这意味着,当您创建随机对象时(例如,在程序开始时),您可能希望从一个新种子开始。大多数人会选择一些与时间相关的值,比如滴答数。

如果要调试程序,给定相同种子的数字序列是相同的事实实际上非常方便:请确保记录种子值,如果出现错误,可以使用相同的种子值在调试器中重新启动程序。这意味着您可以准确地重播场景。如果你能使用一个真正的随机数生成器,这是不可能的。


使用相同的种子值,单独的随机实例将返回/生成相同的随机数序列;更多信息请参见:http://www.particle.kth.se/~lindsey/javacourse/book/part1/tech/chapter04/javarandnums.html

Ruby示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class LCG; def initialize(seed=Time.now.to_i, a=2416, b=374441, m=1771075); @x, @a, @b, @m = seed % m, a, b, m; end; def next(); @x = (@a * @x + @b) % @m; end; end

irb(main):004:0> time = Time.now.to_i
=> 1282908389

irb(main):005:0> r = LCG.new(time)
=> #<LCG:0x0000010094f578 @x=650089, @a=2416, @b=374441, @m=1771075>
irb(main):006:0> r.next
=> 45940
irb(main):007:0> r.next
=> 1558831
irb(main):008:0> r.next
=> 1204687
irb(main):009:0> f = LCG.new(time)
=> #<LCG:0x0000010084cb28 @x=650089, @a=2416, @b=374441, @m=1771075>
irb(main):010:0> f.next
=> 45940
irb(main):011:0> f.next
=> 1558831
irb(main):012:0> f.next
=> 1204687

根据值a/b/m,给定种子的结果相同。这可用于在两个位置生成相同的"随机"数字,并且双方可以依赖于获得相同的结果。这对于加密很有用;尽管很明显,这个算法在加密上并不安全。