对java中random的思考

今天又一次去看jdk 7的api的random的时候,对random怎么实现的伪随机数很好奇,在百度中搜索了一下,然后得到了一些启示。

     JDK 中有两个随机数类:
            一个是 PRNG,也就伪随机数类 java.util.Random,是采用线性同余算法产生的。
   另一个是 RNG,也就是 java.util.Random 的子类强随机数 java.security.SecureRandom,这是一个 SPI 类,也就是说具体的算法由 Provider 提供。Sun 给其提供了一个默认的算法——SHA1PRNG。
   由于 Random 是采用时间作为随机数种子,如果 hacker 知道随机数产生的时间,那就能重现随机数。而 SecureRandom 属于强随机数,一般不单独采用时间作为随机数种子,还会采用临时文件夹中大小,某个线程从休眠到被唤醒所耗的时间等等一系列无法重现的值作为随机数种子。
SecureRandom 一般用于安全、加密 API,以及 UUID 的生成。

但是什么是线性同余算法以及random怎么实现的random呢?

线性同余方法(LCG)是个产生伪随机数的方法。

它是根据递归公式:

N_{j+1} \equiv (A \times N_j + B ) \pmod{M}    也可以不加B。

其中A,B,M是产生器设定的常数。

LCG的周期最大为M,但大部分情况都会少于M。要令LCG达到最大周期,应符合以下条件:

  1. B,M互质
  2. M的所有质因子的能整除A-1
  3. M是4的倍数A-1也是;
  4. A,B,N_0都比M小;
  5. A,B是正整数。

    线性同余算法有m 、a 、c 和X0 4个参数,通过置Xn + 1 ≡aXn + c (mod m) ,求得随机数序列< Xn > , 这个序列称作线性同余序列。m、a 、c 和X0 分别称做模数、乘数、增量和初始值。线性同余方法速度快,如果对乘数和模数进行适当的选择,可以满足用于评价一个随机数产生器的3 种准则:
1.这个函数应该是一个完整周期的产生函数。也就是说,这个函数应该在重复之前产生出0 到m之间的所有数;
2.产生的序列应该看起来是随机的;
3.这个函数应该用32bit 算术高效实现。

例如在我的算法中,a=7^5;c=0;m=2^31-1; x0为系统时间,但是系统时间,不是很安全,可以增加其他的变量来使这个值更加安全。




猜你喜欢

转载自blog.csdn.net/zhangwenjiezw886/article/details/46505613