java中随机数的”真真伪伪“

342 阅读3分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

java中的随机数是有三种生成方法。分别如下:

  1. Math中的random()

  2. java.util.Random

  3. System.currentTimeMillis()

先不说这些随机数的用法,我们先讨论关于方法2——java.util.Random的伪随机数问题。在最初学习随机数的过程中,我总是难以理解伪随机数的意思。难道随机数还会有“伪”这种说法吗?随机数不就是在很多数字中随机选取所得的吗?

在后来查阅资料与观看一系列的视频学习后,我逐渐理解了这个“伪”字的真正含义。

伪随机数是用确定性的算法计算出来自[0,1]均匀分布的随机数序列。并不真正的随机,但具有类似于随机数的统计特征,如均匀性、独立性等。在计算伪随机数时,若使用的初值(种子)不变,那么伪随机数的数序也不变。

以上是百度百科对伪随机数的定义。对于定义我暂时没有深入的研究,我使用以下的实验得到了伪随机数的“伪”。

实验一

第一次我们实验两个Random生成的随机数,不设置种子

package 随机数测试;

import java.util.Random;

public class Test1 {
    public static void main(String[] args) {
        Random a = new Random();
        Random b = new Random();
        System.out.println("a=" + a.nextInt() + ",b=" + b.nextInt());
    }
}
第一次运行结果
a=-1420468450,b=-685853092
第二次运行结果
a=2003067673,b=-1073325390

我们可以看到第一次的运行结果a、b结果不同,且第一次与第二次的运行结果也各不相同。这样的结果并不能说明Random生成的就是伪随机数。

实验二

我们实验两个Random生成的随机数,设置不同的种子

package 随机数测试;

import java.util.Random;

public class Test1 {
    public static void main(String[] args) {
        Random a = new Random(15);
        Random b = new Random(10);
        System.out.println("a=" + a.nextInt() + ",b=" + b.nextInt());
    }
}
第一次运行结果
a=-1159716814,b=-1157793070
第二次运行结果
a=-1159716814,b=-1157793070

我们可以发现不同的种子,产生了不同的随机数,但第二次的运行结果却和第一次的运行结果一致,并没有达到随机的效果。由此我们可以确定通过java.util.Random这种方法生成的随机数。

而第一次的实验结果是因为new Random()的无参数构造方法会默认以系统时间的毫秒数作为随机种子,而毫秒数在时时刻刻变化,所以实质上就是参数不同所导致的随机数的产生不同。

实验三

为了验证伪随机数,我们开始第三个实验,两个Random生成的随机数,设置相同的种子。

package 随机数测试;

import java.util.Random;

public class Test1 {
    public static void main(String[] args) {
        Random a = new Random(15);
        Random b = new Random(15);
        System.out.println("a=" + a.nextInt() + ",b=" + b.nextInt());
    }
}
第一次运行结果
a=-1159716814,b=-1159716814
第二次运行结果
a=-1159716814,b=-1159716814

结果如预料中的一样。