在前两天学习了使用python实现伪随机数的方法,今天是时候来做一个总结了。
首先要说明的是什么是随机数,真正的随机数是使用物理现象产生的:比如掷钱币、骰子、转轮、使用电子元件的噪音、核裂变等等。产生这些随机数的方法有很多种,而这些产生随机数的方法就称为随机数生成器。像前面说的由物理现象所产生的随机数发生器叫做物理性随机数发生器,它们的缺点是技术要求比较高。
但是在我们的实际生活中广泛应用的是伪随机数生成器,所谓的“伪”就是假的的意思,也就是说并不是真正的随机数。那么这些随机数是怎么实现的呢?这些数字是由固定的算法实现的,是有规律可循的,并不能实现真正的“随机”,但是它们具有类似于随机数的统计特征。这样的发生器叫做伪随机数发生器。
实现伪随机数的方法有很多种,如:平方取中法,线性同余法等方法。
下面主要介绍的是线性同余法,如C的rand函数和JAVA的java.util.Random类就是使用该方法实现的,其公式为:
<
其中, a称为乘数,b称为增量,(end-start)称为模数,它们均为常数。
然后设置rOld = rNew,一般要求用户指定种子数rOld(也称为seed),当然也可以自由选择a和b,但是两个数如果选择不好,可能会影响数字的随机性 ,所以一般令:
a=32310901
b=1729
这样使得生成的随机数最均匀。下面我是用的将种子自定义设为999999999。代码如下:
def myrandint( start,end,seed=999999999 ):
a=32310901 #产生出的随机数最均匀
b=1729
rOld=seed
m=end-start
while True: #每调用一次这个myrandint函数,才生成一次随机数 所以要惰性求值
rNew = (a*rOld+b)%m
yield rNew
rOld=rNew
#模拟使用20个不同的种子来生成随机数
for i in range(20):
r = myrandint(1,10000, i)
#每个种子生成10个随机数
print('种子',i,'生成随机数')
for j in range(10):
print( next(r),end=',' )
print( )
运行结果是使用20个不同的种子生成的随机数。
但是,这样将种子设为固定值是不合理的。
r = myrandint(1,10000,2)
print(r.__next__())
print(r.__next__())
运行结果为:
9993
6934
当再次运行代码:
r = myrandint(1,10000,2)
print(r.__next__())
运行结果仍然是:9993
这便不能体现随机,因此常采用系统时间作为种子来实现该算法。以上代码只需将seed设为系统时间便可以实现。