随机数怎么样随机的
介绍
都说计算机的随机都是伪随机,其实无论是生活的各个角落都是伪随机而不是真随机,真随机可能真的不存在,所有的事件都可以用简单的P(A)表示,无论是否有条件,那么我们如果实现这种随机呢?
随机算法
随机数对人来说可能是随机的也可能不是,处于量子态,不过目前的计算机所生成的随机数其实不算真随机,而是一种周期很大的循环数,那这样的数怎么生成呢?
线性同余法[LCG]
这种方法较为常用,在《C primer plus》中介绍了一段魔术语句,可以实现随机数,那么很多人可能好奇为什么这串代码可以生成随机数,这些已知的数字都是什么含义等等。
1 |
|
其实学过数学的人都对这种Ax+B的格式不陌生,一般都以线性开头命名,即线性同余算法,这种算法用通式表示为:
其中最大周期为C,A、B均为整数且C的所有因数中的质数都可以被A-1整除,即满足C%(A-1)==0
对于A、B是经过计算得到的,通过移位运算不难算出重复周期为2^15-1即(1<<15)-1。代码中的种子常使用时间。在C++的Random头文件中使用了这种算法。
平方取中法
这个算法的爹是冯诺依曼,算法主要讲的是:给定一个m位数记作x,其中m是偶数(基数计算带分数),计算x的平方,得到2m位数(不足在首端补0)然后从乘数中间得到m位数,然后重复这一步骤。
梅森旋转(Mersenne Twister)算法
衡量梅森旋转(MT)的质量,需要使用K分布,K分布的定义是:一个周期为T的随机序列Xi,每一位都有w位,当满足下面条件就成为w位的K分布
假设f(x)表示x的前v位形成的数字,并且长度为P的kv位序列:
($f(x_i)$,$f(x_{i+1})$,$f(x_{i+2})$…….$f(x_{i+k-1})$)
其中每个可能出现的$2^{kv}$组合在一个周期内出现相同的次数(除全0序列出现次数次数比其他序列少1次)
算法需要借助线性反馈移位寄存器(LFSR)生成随机数,主要使用的运算符是异或(xor),我们采用8位寄存器的形式演示,初始化寄存器位10001010,然后定义反馈函数为:
所以我们根据x的重数可知,只需对第8、4、2、1按顺序做一次异或即可。然后丢掉最后一位,把当前结果插入首端。然后循环这个过程多次,就得到了随机序列。这便是旋转的过程。
我们使用C++实现这个过程。
1 |
|
通过修改传递的MT_random参数就可以得到不同的随机数
结语
通过阅读本文,读者可以了解随机数生成的基本过程,也能了解背后的理论基础,同时对MT算法可以深入理解。
MT算法部分参考: