matlab中的伪随机数原理

要说matlab的随机函数,就得先说说伪随机数。不过我也只能从matlab 应用的角度,从使用时的概念角度讲讲,梳理一下自己粗浅的理解。至于数理方面的,就没认真看过。真正的随机数是得通过现实世界中随机发生的物理事件来产生的,如放射性物质随机数发生器是通过某种放射性物质放射出的粒子数来获得随机数,还有通过电路产生高频噪声来获得随机数等。不过这种硬件随机数发生器价格都比较贵,如使用比较广泛的ComScire的随机数发生器价格在895美元,约合人民币6000元以上。但是很多软件,PC机都需要使用随机数,这么贵的价格对一般应用来说不能每台PC都买一个硬件随机数发生器。在这种原因下,就出现了使用软件方法来产生随机数的算法。通过软件方法产生的随机数都成为伪随机数,因为它们都不是真正的随机数。
所谓伪随机数,就是找到一组数目巨大的数,这组数的出现符合一定的概率分布,并且这组数能通过相应的随机性测试,这样我们就能使用这组数来凑合“顶替”真正的随机数来应用了。但是由于其本质仅仅是用一组确定的数对真随机数所表现出来的相关性质的近似,在有些场合下就无法满足应用要求,或者说是“随机性质不够了”,如现在使用最广泛的一种伪随机数产生算法,线性同余算法,无法满足蒙特卡罗模拟对随机性的要求。matlab默认使用的随机数生成算法 Mersenne twister是目前较好的一种伪随机数产生算法,可以满足很多场合的应用,如蒙特卡罗模拟等。所有满足不同分布的伪随机数,都可以通过对均匀分布伪随机数的数学变换得到,均匀分布伪随机数的产生算法,是伪随机数产生算法的根基,前面的线性同余算法,Mersenne twister算法,都是均匀分布伪随机数的产生算法。
伪随机数的产生,一般都是这样的情况,首先是选取种子,然后是在此种子基础上根据具体的生成算法计算得到一个伪随机数,然后利用此伪随机数再根据生成算法递归计算出下一个伪随机数,直到将所有不重复出现的伪随机数全部计算出来。这个伪随机数序列就是我们以后要用到的伪随机数序列。上面的计算过程可以一次性计算完毕,也可以使用一次递归计算一次,每次生成的伪随机数就是这个伪随机数序列中的一个,不过不管怎么样,只要确定了种子,确定了生成算法,这个序列就是确定的了。所谓种子,就是一个对伪随机数计算的初始值。既然是确定的了,那么当我们使用某种算法计算给出一个伪随机数,那么下一次计算时出现的数也就是固定的,有人可能会问,既然是固定的,还有什么随机性?这就是伪随机数的“伪”所在了。伪随机数的“随机”在于,虽然下次计算产生的数是一个固定的数,但是这种出现的模式,以及整个伪随机数序列,却能通过大部分随机性测试实验,这说明对随机性测试实验来说,伪随机数的表现同真随机数接近,这样我们在一些不是很苛刻的应用场合,就能拿这组伪随机数来用,使用时的外在表现同真随机数是较近似的。
好了,现在才要说matlab的随机函数,matlab的随机函数产生的随机数都是根据伪随机数序列获取的,在v7.7以上的版本中,有如下的伪随机数产生器:Mersenne twister,Multiplicative congruential generator,Multiplicative lagged Fibonacci generator,Combined multiple recursive generator,Shift-register generator summed with linear congruential generator,Modified subtract with borrow generator。相关的指令即可选择不同的产生器。默认的情况下,matlab在启动时总是将各个产生器的种子设为0,这样造成编写的包含随机函数的程序每次运行的结果都是固定的,为了改变这种情况,可以将系统时间设置为种子(RandStream.setDefaultStream(RandStream('mt19937ar','Seed',sum(100*clock)))),这样每次matlab启动时种子设置的不同会使得计算得到的随机序列不同。在7.7版本以上,随机序列的生成通过RandStream对象来实现,与 7.7以前的版本不同。
RandStream对象的使用可简单总结如下:要生成一个随机数,首先需要一个伪随机数序列,这个序列通过设定种子和生成算法来确定,RandStream的构造函数或RandStream.create方法即用来完成此任务。然后我们需要使用 RandStream.setDefaultStream函数将确定好的序列对象设置为当前matlab使用的序列。然后通过rand等函数就可以用此序列生成随机数了。当然也可以不用将其设置为默认序列,使用rand函数可以指定从哪个序列中生成随机数:
stream=RandStream('mrg32k3a');
rand(stream,1,5)
使用RandStream.create函数可以创建独立同分布的随机序列,如
[s1,s2,s3] = RandStream.create('mrg32k3a','NumStreams',3);
r1 = rand(s1,100000,1); r2 = rand(s2,100000,1); r3 = rand(s3,100000,1);
corrcoef([r1,r2,r3])
要使得前后两次生成的随机数保持一样,可以将递归计算的过程中的伪随机数状态记录下来,然后下一次计算总是基于这个记录下来的伪随机数状态来进行,这样每次计算得到的随机数就总是相同的:
defaultStream = RandStream.getDefaultStream;
savedState = defaultStream.State;
u1 = rand(1,5)
defaultStream.State = savedState;
u2 = rand(1,5)
各个指令具体的使用方法可以通过helpdesk命令,搜索RandStream来查看。v7.7以上版本为了与旧版本保持兼容,保留了原来如 rand('state',0)这种伪随机序列设置方法,称之为legacy mode,有关legacy mode的内容也可以在RandStream项中找到。
上一篇:国际跳棋的开局


下一篇:Matlab得到运行时间