线性同余算法以及java中随机数的实现分析

        关于随机数的生成,其实方法有很多,主要分为两类,硬件生成和软件生成。

        先说下硬件生成的方法,芯片厂商intel出产的就有一种芯片,专门用于生成随机数,其原理是利用电阻和振荡器来产生噪声作为信息源生成随机数。噪声一般都是无规律的,因此利用此方法生成的肯定就是真随机数了。此芯片一般集成在intel芯片组中。其实我们一般见的电路中都是有噪声的,只不过该噪声对电路实现的功能影响不大,而且一般的电路都有减弱噪声的功能模块来削弱噪声。另外还有一些比较专业的产生真随机数的芯片厂商,实现方法是利用测不准原理。也就是说电子相对于原子核的位置和当前的时间关系是测不准的。一般学过高中化学的童鞋都听说过测不准原理。这种芯片在国内其实是经常用到的。比如我们的彩票行业。主要用这种方法来实现中奖号码的选取,之所以不用电路噪声来生成这里的随机数,那是因为电路噪声容易受到干扰,做过片上系统开发的童鞋也应该知道,我们针对芯片编写的程序,容易受到外界的干扰,比如在只读存储器上写的程序,受到紫外线照射后,程序容易丢失,在一般芯片上跑的程序,如果一辆汽车刚好经过这里,程序也会容易出错。呵呵。这些都是噪声影响了程序的运行。

        上面简单的说了下硬件生成的方法。其实我主要想说说软件的实现。在不同语言中,都有类似的实现方法。最流行的莫过于高德纳大师在TAOCP一书中描写的线性同余算法了。该算法能够生成伪随机数。

        算法的公式如下:

                X(n+1) = (a * X(n) + c) % m

     模m, m > 0
     系数a, 0 < a < m
     增量c, 0 <= c < m
     原始值(种子) 0 <= X(0) < m
     其中参数c, m, a比较敏感,或者说直接影响了伪随机数产生的质量。

     以上的描述是摘自维基百科。

      %在编程中叫做取余数,也就是说超过m后,即减去m,这样生成的数字会在m范围内,在数学领域叫做同余。

      满足以上的公式,生成出来的x(n+1)则是一个伪随机数。当我看到这里后,真的感慨数学的伟大呀。看看java里面是怎么实现的吧。

       

package com.bplead.random;

import java.util.Date;
import java.util.concurrent.atomic.AtomicLong;

public class Random {
	
	private final AtomicLong seed;
	private final static long multiplier = 0x5DEECE66DL;
	private final static long addend = 0xBL;
	private final static long mask = (1L << 48) - 1;
	private static volatile long seedUniquifier = 8682522807148012L;
	
	public void srandSeed(long t){
        this.seed.set(t);
	}
	
	public Random(){
		 this(++seedUniquifier + System.nanoTime());
		 System.out.println(seed.get());
	}
	
	public Random(long seed) {
        this.seed = new AtomicLong(0L);
        srandSeed(seed);
    }
	
	int random(int bits){
		long oldseed = seed.get();
		long nextseed = (oldseed * multiplier + addend) & mask;
		return (int)(nextseed >>> (48 - bits));
	}
	
	public static void main(String[] args) {
		Random r = new Random();
		r.srandSeed(new Date().getTime());
		System.out.println(r.random(32));
	}
}
        我先把代码贴出来,这个是我自己写的,比较简单,不像java类库中那样考虑全面,但是也是经过分析jdk后得出的结论。

        我已经不想讲这里的参数如何和上面的公式对应了。会java的都明白。只是源代码里面的实现很精深,我 只列举以下几点:

        1 this的用法,平时见过的只有用this引用私有成员变量,但是这里的用法,比较诡异,实现的功能就是给没有初始化的私有成员变量赋值了。

        2 AtomicLong对象的使用,其实这个对象就是实现同步以后的long类型了。具体用法还是google吧。

        3 这一个参数的选取,是有很大意义的,具体为什么会选这样的参数,我目前也不是很明白。

  

        

你可能感兴趣的:(算法)