博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
2. Java走过的坑-不随便设置随机种子
阅读量:7197 次
发布时间:2019-06-29

本文共 1966 字,大约阅读时间需要 6 分钟。

  hot3.png

下面来看一段代码

public class RandomSeed {    public static void main(String[] args) {        Random random = new Random();        for(int i=1; i<4; i++){            System.out.println("第"+ i +"次" + random.nextInt());        }    }}控制台输出第1次-1994303606第2次-187157822第3次-1572664715

代码很简单,我们一般也都是这么获取随机数的,我们看到除数的三次结果都是不同的,也都是随机数,下面再看看一组程序

public static void main(String[] args) {    // 多运行几次    Random random = new Random(1000);    for(int i=1; i<4; i++){        System.out.println("第"+ i +"次" + random.nextInt());    }}控制台输出第1次-1244746321第2次1060493871第3次-1826063944

计算机不同输出的随机数也不同,但有一点是相同的:在同一台机器上不管允许多少次,打印出的随机数都是相同的,也就是说第一次运行会打印出这三个随机数,第二次打印还是这三个随机数,出现问题了,现在不是随机数不随机了吗?

我们找找问题何在,那是因为产生随机数的"种子"被固定了,在Java中随机数的产生取决于种子,随机数和种子之间应该遵守以下规则:

  • 种子不同,产生不同的随机数

  • 种子相同,实例不同产生不同的随机数

看完上面2个规则,用代码来解释

// 这是JDK中random类的无参构造函数public Random() {    this(seedUniquifier() ^ System.nanoTime());}private static long seedUniquifier() {        // L'Ecuyer, "Tables of Linear Congruential Generators of        // Different Sizes and Good Lattice Structure", 1999        for (;;) {            long current = seedUniquifier.get();            long next = current * 181783497276652981L;            if (seedUniquifier.compareAndSet(current, next))                return next;    }}private static final AtomicLong seedUniquifier = new AtomicLong(8682522807148012L);

取了seedUniquifier ^ System.nanoTime()的返回值,seedUniquifier的代码我没细看,总之就是设置当前种子的算法,看来这样的不会重复的随机数了。

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);        }    }

这段代码是传入了一个参数的随机,实际上我们设定了随机种子是1000,运行多次的随机数是一样的因为永远都走

this.seed = new AtomicLong(initialScramble(seed));

这一步,虽然返回的是不同的实例,但是固定的种子还是会导致多次运行出现相同的随机数。

总结:

在java中有2种方法可以获取随机数:

java.util.Random和Math.random() 获取随机数,两者功能相同,一般非必须情况不要设置随机种子。

转载于:https://my.oschina.net/biezhi/blog/397994

你可能感兴趣的文章
bash快捷方式
查看>>
php DOC类型注释的用法
查看>>
浏览器兼容问题踩坑收集
查看>>
H5视频推流方案
查看>>
【BZOJ】3998: [TJOI2015]弦论
查看>>
【CodeForces】698 C. LRU
查看>>
波浪刻度电池View
查看>>
转 网络编程学习笔记一:Socket编程
查看>>
HSTS VS 301 redirect
查看>>
第七周作业
查看>>
如何在androidstudio中运行java程序
查看>>
Http协议
查看>>
C++中消息自动派发之一 About JSON
查看>>
MongoDB系列:三、springboot整合mongoDB的简单demo
查看>>
WPF中触发器Trigger、MultiTrigger、DataTrigger、MultiDataTrigger、EventTrigger几种
查看>>
Linux 内核 链表 的简单模拟(1)
查看>>
第一个开源项目---halcon图像显示控件(缩放/roi操作)
查看>>
13.Axis创建webservice客户端和服务端
查看>>
ZOJ 1586-Preliminary Round
查看>>
在 WebBrowser 的任意页面中安装 jQuery 操作页面元素 - IEBrowser [4]
查看>>