Java:Random函数及其种子的作用
伪随机(preundorandom):通过算法产生的随机数都是伪随机!!
只有通过真实的随机事件产生的随机数才是真随机!!比如,通过机器的硬件噪声产生随机数、通过大气噪声产生随机数
Random生成的随机数都是伪随机数!!!
是由可确定的函数(常用线性同余),通过一个种子(常用时钟),产生的伪随机数。这意味着:如果知道了种子,或者已经产生的随机数,都可能获得接下来随机数序列的信息(可预测性)
Random类拥有两个构造方法,用于实现随机数生成器:
| Random( ) | 构造一个随机数生成器 |
| Random(long seed) | 用种子seed构造一个随机数生成器 |
一、无参构造方法(不设置种子)
虽然表面上看我们未设置种子,但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());
} 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);
生成种子过程:(参考解密随机数生成器(二)——从java源码看线性同余算法)
1、获得一个长整形数作为“初始种子”(系统默认的是8682522807148012L)
2、不断与一个变态的数——181783497276652981L相乘(天知道这些数是不是工程师随便滚键盘滚出来的-.-)得到一个不能预测的值,直到 能把这个不能事先预期的值 赋给Random对象的静态常量seedUniquifier 。因为多线程环境下赋值操作可能失败,就for(;;)来保证一定要赋值成功
3、与系统随机出来的nanotime值作异或运算,得到最终的种子
nanotime算是一个随机性比较强的参数,用于描述代码的执行时间。源码中关于nanotime的描述(部分):
/**
* Returns the current value of the running Java Virtual Machine's
* high-resolution time source, in nanoseconds.
*
* <p>This method can only be used to measure elapsed time and is
* not related to any other notion of system or wall-clock time.
二、有参构造方法(设置种子)
语法:Random ran = Random(long seed)
有参构造方法的源码如下:
/**
* Creates a new random number generator using a single {@code long} seed.
* The seed is the initial value of the internal state of the pseudorandom
* number generator which is maintained by method {@link #next}.
*
* <p>The invocation {@code new Random(seed)} is equivalent to:
* <pre> {@code
* Random rnd = new Random();
* rnd.setSeed(seed);}</pre>
*
* @param seed the initial seed
* @see #setSeed(long)
*/
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);
}
} private static long initialScramble(long seed) {
return (seed ^ multiplier) & mask;
}
其中的multiplier和mask都是定值:
private static final long multiplier = 0x5DEECE66DL; private static final long mask = (1L << 48) - 1;
三、代码测试
分别采用有参和无参两种方法,生成[0, 100)内的随机整数,各生成五组,每组十个随机数:
import java.util.Random;
public class RandomTest {
public static void main(String[] args) {
RandomTest rt = new RandomTest();
rt.testRandom();
}
public void testRandom(){
System.out.println("Random不设置种子:");
for (int i = 0; i < 5; i++) {
Random random = new Random();
for (int j = 0; j < 10; j++) {
System.out.print(" " + random.nextInt(100) + ", ");
}
System.out.println("");
}
System.out.println("");
System.out.println("Random设置种子:");
for (int i = 0; i < 5; i++) {
Random random = new Random();
random.setSeed(100);
for (int j = 0; j < 10; j++) {
System.out.print(" " + random.nextInt(100) + ", ");
}
System.out.println("");
}
}
}
运行结果如下:

结论:
虽然二者都是伪随机,但是,无参数构造方法(不设置种子)具有更强的随机性,能够满足一般统计上的随机数要求。使用有参的构造方法(设置种子)无论你生成多少次,每次生成的随机序列都相同,名副其实的伪随机!!
Java:Random函数及其种子的作用的更多相关文章
- Java Random函数
Java中存在着两种Random函数: 1.java.lang.Math.Random: 调用这个Math.Random()函数能够返回带正号的double值,该值大于等于0.0且小于1.0,即取值范 ...
- JAVA中的Random()函数
Java中存在着两种Random函数: 一.java.lang.Math.Random; 调用这个Math.Random()函数能够返回带正号的double值,该值大于等于0.0且小于1.0,即取值范 ...
- tips:Java的Random类和Random函数
tips:Java的Random类和Random函数! 随机数是一个很有趣的东西,在java中可以通过下面这2种方法得到: (1)Random类: Random类是java.util.Random这个 ...
- Java - 经常使用函数Random函数
http://blog.csdn.net/pipisorry/article/details/44411541 Random()函数生成随机数 java.util.Random 在Java的API帮助 ...
- random函数
Java中存在着两种Random函数: 一.java.lang.Math.Random; 调用这个Math.Random()函数能够返回带正号的double值,该值大于等于0.0且小于1.0,即取值范 ...
- random函数详解
1. 随机函数 Math.random() Math.random(); 取值范围是 [ 0.0,1.0 ) 的左闭右开区间.具体源代码如下所示: Math.random()是生成0~ ...
- java Random类和Math.Rondom
Java中存在着两种Random函数: 一.java.lang.Math.Random; 调用这个Math.Random()函数能够返回带正号的double值,该值大于等于0.0且小于1.0,即取 ...
- JAVA Random 详解
Java中存在着两种Random函数: 一.java.lang.Math.Random; 调用这个Math.Random()函数能够返回带正号的double值,该值大于等于0.0且小于1.0,即取值范 ...
- C#Random函数在循环中每次获取一样的值
首先需要了解一点Random函数的随机生成是和当前时间有关系,如果在短时间生成随机数,就会导致随机数生成出来是相同的. 不过我们可以在每次随机时指定一个Seed种子值,这样在循环里就可以每次获取不一样 ...
随机推荐
- 布局方式-flex布局
.弹性盒子 .盒子本来就是并列的 .指定宽度即可 <style> .container { width: 800px; height: 200px; display: flex; bord ...
- 【翻译】苹果官网的命名规范之 Naming Properties and Data Types
苹果官方原文:Naming Properties and Data Types 前言:纯属练习英语和学习.翻译错误和不通顺的地方敬请谅解和指正.O(∩_∩)O 属性和数据类型的命名 本节讲述了属性定义 ...
- Consider defining a bean of type 'package' in your configuration [Spring-Boot]
https://stackoverflow.com/questions/40384056/consider-defining-a-bean-of-type-package-in-your-config ...
- P2852 [USACO06DEC]牛奶模式Milk Patterns
link 这是一道后缀匹配的模板题 我们只需要将height算出来 然后二分一下答案就可以了 #include<cstdio> #include<algorithm> #inc ...
- Android UI开发专题(转)
http://dev.10086.cn/cmdn/bbs/viewthread.php?tid=18736&page=1#pid89255 Android UI开发专题(一) 之界面设计 近期 ...
- 通过sql语句查询出来的结果字段没有到对应实体类时的处理方法
通过sql语句查询出来的结果字段没有到对应实体类时的处理方法,对于Person类获取用户第一个名字和年龄两个字段,常见的有两种方式: 1.在创建一个与查询结果字段对应的类,然后通过构造函数实现: Qu ...
- 时空隧道FQ
给你推荐一款海外网站加速工具,为科技工作者.海外归国人员.企业团队.外贸工作者提供海外上网服务,永久免费. 国外网址:https://chrome.google.com/webstore/detail ...
- Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition
Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition Kaiming He, Xiangyu Zh ...
- MVVM及框架的双向绑定
MVVM由以下三个内容组成 View:视图模板 Model:数据模型 ViewModel:作为桥梁负责沟通View和Model,自动渲染模板 在JQuery时期,如果需要刷新UI时,需要先取到对应的D ...
- 与JSON相关的问题
1.JSON.stringify 与 JSON.parse 相关的问题 JSON.stringify 把字符串转化为字符串,JSON.parse把字符串转化为JSON格式 会出现的问题Unexpect ...