rand()函数实现原理:线性同余法

转载自:http://www.cnblogs.com/xkfz007/archive/2012/03/27/2420154.html

      关于“随机数”产生有许多算法,但无论如何,都不可能产生真正随机数,因为电脑程序是个确定状态转换机,一种输入必定产生一种确定输出。   
但要实现“不可预知”还是可以做到的,只需有“不可预知”的输入或者初始化就可以了,像系统时间,网络实时带宽,Cpu使用率等等都可以作为“不可预知”的量来初始化随机函数。

      产生整数rand的原理是:   
      y=(ax+b)(mod  n)。其中n一般是一个很大的素数(几万)。a也是大素数,而且a,b,n都是常数。所以rand的产生决定于x,他被称seed。每一个seed都是上一次产生的y的函数。这样,如果直接取seed=y的话,虽然产生的rand之间相关性甚小,但只要知道某个y,就能推知以后的rand。   为避免这种情况,一般取seed为y和当时计算机的时间的函数,如seed=y+t系统里的随机数是利用初等数论中的同余定理来实现的.  比如C中对于rand()函数是如下实现的.   

1
2
3
4
5
6
7
8
9
10
11
12
unsigned  long  int  next = 1;
/* rand:  return pseudo-random integer on 0..32767 */
int  rand ( void )
{
     next = next * 1103515245 + 12345;
     return  (unsigned  int )(next / 65536) % 32768;
}
/* srand:  set seed for rand() */
void  srand (unsigned  int  seed)
{
     next = seed;
}

      另外一个高级一点的随机数生成为:

下面是源代码:

unsigned int x = 123456789,
                   y = 362436000,
                   z = 521288629,
                   c = 7654321; /* Seed variables */ 
 
unsigned int KISS()
{  
    unsigned long long t, A = 698769069ULL;  

    x = 69069*x+12345;  
    y ^= (y<<13); 
    y ^= (y>>17); 
    y ^= (y<<5);  
    
    t = (A*z + c);
    c = (t >> 32);
    z = t;
     
    return x+y+z;  
}

      居然就只是把“线性同余”,“移位轮转”和“带记忆乘法”这3种基本的随机数发生法一起用,便获得很好的效果。的确够巧的,从这一点上说,比Mersenne Twister要有趣多了。而且通过它,我们一次就学会3种随机数发生法。抽出其中任何1种,都可以单独使用,仿佛一把瑞士军刀。

      线性同余法生成的是伪随机数,粗略符合均匀分布。根据中心极限定理,任何分布的噪声,通过反复相加,就可以成为高斯噪声。

你可能感兴趣的:(C++)