伪随机(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函数及其种子的作用的更多相关文章

  1. Java Random函数

    Java中存在着两种Random函数: 1.java.lang.Math.Random: 调用这个Math.Random()函数能够返回带正号的double值,该值大于等于0.0且小于1.0,即取值范 ...

  2. JAVA中的Random()函数

    Java中存在着两种Random函数: 一.java.lang.Math.Random; 调用这个Math.Random()函数能够返回带正号的double值,该值大于等于0.0且小于1.0,即取值范 ...

  3. tips:Java的Random类和Random函数

    tips:Java的Random类和Random函数! 随机数是一个很有趣的东西,在java中可以通过下面这2种方法得到: (1)Random类: Random类是java.util.Random这个 ...

  4. Java - 经常使用函数Random函数

    http://blog.csdn.net/pipisorry/article/details/44411541 Random()函数生成随机数 java.util.Random 在Java的API帮助 ...

  5. random函数

    Java中存在着两种Random函数: 一.java.lang.Math.Random; 调用这个Math.Random()函数能够返回带正号的double值,该值大于等于0.0且小于1.0,即取值范 ...

  6. random函数详解

    1. 随机函数  Math.random() Math.random();    取值范围是  [ 0.0,1.0 )  的左闭右开区间.具体源代码如下所示:   Math.random()是生成0~ ...

  7. java Random类和Math.Rondom

      Java中存在着两种Random函数: 一.java.lang.Math.Random; 调用这个Math.Random()函数能够返回带正号的double值,该值大于等于0.0且小于1.0,即取 ...

  8. JAVA Random 详解

    Java中存在着两种Random函数: 一.java.lang.Math.Random; 调用这个Math.Random()函数能够返回带正号的double值,该值大于等于0.0且小于1.0,即取值范 ...

  9. C#Random函数在循环中每次获取一样的值

    首先需要了解一点Random函数的随机生成是和当前时间有关系,如果在短时间生成随机数,就会导致随机数生成出来是相同的. 不过我们可以在每次随机时指定一个Seed种子值,这样在循环里就可以每次获取不一样 ...

随机推荐

  1. 布局方式-flex布局

    .弹性盒子 .盒子本来就是并列的 .指定宽度即可 <style> .container { width: 800px; height: 200px; display: flex; bord ...

  2. 【翻译】苹果官网的命名规范之 Naming Properties and Data Types

    苹果官方原文:Naming Properties and Data Types 前言:纯属练习英语和学习.翻译错误和不通顺的地方敬请谅解和指正.O(∩_∩)O 属性和数据类型的命名 本节讲述了属性定义 ...

  3. 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 ...

  4. P2852 [USACO06DEC]牛奶模式Milk Patterns

    link 这是一道后缀匹配的模板题 我们只需要将height算出来 然后二分一下答案就可以了 #include<cstdio> #include<algorithm> #inc ...

  5. Android UI开发专题(转)

    http://dev.10086.cn/cmdn/bbs/viewthread.php?tid=18736&page=1#pid89255 Android UI开发专题(一) 之界面设计 近期 ...

  6. 通过sql语句查询出来的结果字段没有到对应实体类时的处理方法

    通过sql语句查询出来的结果字段没有到对应实体类时的处理方法,对于Person类获取用户第一个名字和年龄两个字段,常见的有两种方式: 1.在创建一个与查询结果字段对应的类,然后通过构造函数实现: Qu ...

  7. 时空隧道FQ

    给你推荐一款海外网站加速工具,为科技工作者.海外归国人员.企业团队.外贸工作者提供海外上网服务,永久免费. 国外网址:https://chrome.google.com/webstore/detail ...

  8. Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition

    Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition Kaiming He, Xiangyu Zh ...

  9. MVVM及框架的双向绑定

    MVVM由以下三个内容组成 View:视图模板 Model:数据模型 ViewModel:作为桥梁负责沟通View和Model,自动渲染模板 在JQuery时期,如果需要刷新UI时,需要先取到对应的D ...

  10. 与JSON相关的问题

    1.JSON.stringify 与 JSON.parse 相关的问题 JSON.stringify 把字符串转化为字符串,JSON.parse把字符串转化为JSON格式 会出现的问题Unexpect ...