javarandom时间种⼦_Java:Random函数及其种⼦的作⽤伪随机(preundorandom):通过算法产⽣的随机数都是伪随机!!
只有通过真实的随机事件产⽣的随机数才是真随机!!
Random⽣成的随机数都是伪随机数!!!
是由可确定的函数(常⽤线性同余),通过⼀个种⼦(常⽤时钟),产⽣的伪随机数。这意味着:如果知道了种⼦,或者已经产⽣的随机数,都可能获得接下来随机数序列的信息(可预测性)
Random类拥有两个构造⽅法,⽤于实现随机数⽣成器:
Random( )
构造⼀个随机数⽣成器
Random(long seed)java生成随机数的方法
⽤种⼦seed构造⼀个随机数⽣成器
⼀、⽆参构造⽅法(不设置种⼦)
虽然表⾯上看我们未设置种⼦,但Random构造⽅法⾥有⼀套⾃⼰的种⼦⽣成机制,源码如下:
1 /**
2 * Creates a new random number generator. This constructor sets
3 * the seed of the random number generator to a value very likely
4 * to be distinct from any other invocation of this constructor.
5 */
6 publicRandom() {
7 this(seedUniquifier() ^System.nanoTime());
8 }9
10 private static longseedUniquifier() {11 //L'Ecuyer, "Tables of Linear Congruential Generators of12 //Different Sizes and Good Lattice Structure", 1999
13 for(;;) {14 long current =();15 long next = current * 181783497276652981L;16
if(seedUniquifierpareAndSet(current, next))17 returnnext;18 }19 }20
21 private static finalAtomicLong seedUniquifier22 = new AtomicLong(8682522807148012L);
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.
*
*
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)
有参构造⽅法的源码如下:
1 /**
2 * Creates a new random number generator using a single {@codelong} seed.
3 * The seed is the initial value of the internal state of the pseudorandom
4 * number generator which is maintained by method {@link#next}.
5 *
6 *
The invocation {@codenew Random(seed)} is equivalent to:7 *
{@code
8 * Random rnd = new Random();9 * rnd.setSeed(seed);}
10 *11 *@paramseed the initial seed12 *@see#setSeed(long)13 */
14 public Random(longseed) {15 if (getClass() == Random.class)16 this.seed = newAtomicLong(initialScramble(seed));17 else{18 //subclass might have overriden setSeed
19 this.seed = newAtomicLong();20 setSeed(seed);21 }22 }23
24 private static long initialScramble(longseed) {25 return (seed ^ multiplier) &mask;26 }
其中的multiplier和mask都是定值:
1 private static final long multiplier = 0x5DEECE66DL;2
3 private static final long mask = (1L << 48) - 1;
三、代码测试
分别采⽤有参和⽆参两种⽅法,⽣成[0, 100)内的随机整数,各⽣成五组,每组⼗个随机数:
1 importjava.util.Random;2
3 public classRandomTest {
4 public static voidmain(String[] args) {
5 RandomTest rt = newRandomTest();6
9 public voidtestRandom(){10 System.out.println("Random不设置种⼦:");11 for (int i = 0; i < 5; i++) {12 Random random = newRandom();13 for (int j = 0; j < 10; j++) {14 System.out.print(" " + Int(100) + ", ");15 }16
System.out.println("");17 }18
19 System.out.println("");20
21 System.out.println("Random设置种⼦:");22 for (int i = 0; i < 5; i++) {23 Random random = newRandom();24
random.setSeed(100);25 for (int j = 0; j < 10; j++) {26 System.out.print(" " + Int(100) + ", ");27 }28
System.out.println("");29 }30 }31 }
运⾏结果如下:
结论:
虽然⼆者都是伪随机,但是,⽆参数构造⽅法(不设置种⼦)具有更强的随机性,能够满⾜⼀般统计上的随机数要求。使⽤有参的构造⽅法(设置种⼦)⽆论你⽣成多少次,每次⽣成的随机序列都相同,名副其实的伪随机!!

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。