Math.random()和Random类

首先Math.random()是令系统随机选取大于等于 0.0 且小于 1.0 的伪随机 double 值,是Java语言常用代码。例如:Number=Math.random()*3+1,设置一个随机1到4的变量;Random 类有含参数和不含参数的构造;其中不含参的构造方法每次都是使用当前系统时间作为种子,而含参构造是使用一个固定值(参数)作为种子(种子也就是Random生成随机数时使用的参数)。每次使用时先创建一个Random对象,也叫随机数生成器,然后调用Random.next**()方法获取数值。

我们存在的疑问有以下几个:
1.Math.random()使用方式;
2.Random的使用方式,有参和无参的区别,使用有参即种子时有何效果;
3.Random.nextInt(n) n的作用;
4.Math.random()和Random之间的关系;

具体的详解,将会有以下代码来辅助解释。

1.Math.random()使用方式:

    System.out.println("通过Math.random产生的随机数列");
        for (int j = 0; j < 8; j++) {
            System.out.println(Math.random() + ",");
        }


输出结果是:

通过Math.random产生的随机数列:

0.8168659689075662,
0.1840193556566645,
0.9640563597086169,
0.7561812266766494,
0.8666184559231468,
0.13803676499296735,
0.599042620405967,
0.11271421452403096,

产生的是double随机数列。

2.Random的使用方式:

首先产生的2个随机数生成器即Random对象,种子是100,代码如下:

     

 for (int i = 0; i < 2; i++) {
            //创建2个随机数生成器
            Random random = new Random(100);
            for (int j = 0; j < 3; j++) {
                //每个随机数生成器产生8个数
                //n 要返回的随机数的边界 也就是随机数的范围是0-50之间的整数
                System.out.println(random.nextInt(50) + ",");
            }
            System.out.println("");
        }


输出结果竟然一直:
15,

0,
24,


15,
0,
24,

由此可见,当使用有参数的构造创建随机数生成器然后生成随机数序列的时候,产生的随机数是种子经过计算得到的,具有相同种子数的Random对象生成的随机数序列相同。其次通过无参构造创建Random对象,其本质是也是种子,只不过种子不是具体的数值,而是系统当前的时间,也因此创建的随机数是不相同的。

代码如下:

        System.out.println("Random不含种子参数\n");
        for (int i = 0; i < 2; i++) {
            //创建2个随机函数生成器
            Random random = new Random();
            for (int j = 0; j < 3; j++) {
                //每个随机数生成器产生3个数
                System.out.println(random.nextInt(50) + ",");
            }
            System.out.println("");
        }
输出结果:
Random不含种子参数
36,
7,
15,


33,
17,
13,

显然产生的随机数是不同的。

PS:random.nextInt (50)代表生成的随机数范围是0-50,不会越界。

我们进行源码分析,关于Random类,其构造源码如下:

  /**
     * Creates a new random number generator. This constructor sets
     * the seed of the random number generator to a value very likely
     * to be distinct from any other invocation of this constructor.
     */
    public Random() {
        this(seedUniquifier() ^ System.nanoTime());
    }


翻译大致:创建一个随机数生成器,此构造方法设置此随机数生成器的种子是独一无二的;
点击this,跳转到对应的有参构造中,显然由代码可以看出种子的生成和当前时间有关系,也因此这样生成的种子是独一无二的。

   public Random(long seed) {
        if (getClass() == Random.class)
            this.seed = new AtomicLong(initialScramble(seed));
        else {
            // subclass might have overriden setSeed
            this.seed = new AtomicLong();
            setSeed(seed);
        }
    }


通过比较我们就可以得出结论:
①随机数是种子经过计算生成的。
②Random类中不含参的构造函数每次都是使用当前时间作为种子,随机性更强;而含参数的构造函数是伪随机的,更有可预见性。
③具有相同种子值的Random对象生成的随机数相同;种子值不同,产生的随机数不再一致。
3.Math.random()和Random之间的关系:

查看源码:

public final class Math { 
     。。。。。省略
     public static double random() {
        return NoImagePreloadHolder.INSTANCE.nextDouble();
    }
     。。。。。省略
    private static class NoImagePreloadHolder {
        private static final Random INSTANCE = new Random();
    }
 
}


从Math类的源码就能看出Math.random()内部调用的方法就是Random类中的nextDouble()方法,此刻也就明确了文章一开始Math.random()返回的是double类型值。
总结:

java.util.Random类中

①随机数是种子经过计算生成的。
②Random类中不含参的构造函数每次都是使用当前时间作为种子,随机性更强;而含参数的构造函数是以参数为种子产生的伪随机数,更有可预见性。
③具有相同种子值的Random对象生成的随机数相同;种子值不同,产生的随机数不再一致。

Math.random()方法中内部调用的方法就是Random类中的nextDouble()方法。
--------------------- 
作者:言方行圆娄知县 
来源:CSDN 
原文:https://blog.csdn.net/yezhuAndroid/article/details/78647984 
版权声明:本文为博主原创文章,转载请附上博文链接!

猜你喜欢

转载自blog.csdn.net/pengzonglu7292/article/details/87457399