zoukankan      html  css  js  c++  java
  • Matlab中rand('state',sum(clock))解析

    一.问题来源

      来自于一份PSO代码,PSO中需要初始化粒子位置和速度。

    二.问题探究

      众所周知,Matlab中的rand()函数产生的是伪随机数,但一般用来也可以接受。但是,如果我们知道伪随机数的初始状态,那么产生的伪随机数是唯一确定的。问题来了,Matlab每次启动会重置rand()和randn()的初始状态(重置为0),也就是说,你产生的随机数会出现两次随机数一模一样的情况,如:

     1 >> rand('state',0) 
     2 >> rand(3,1)
     3 
     4 ans =
     5 
     6     0.9501
     7     0.2311
     8     0.6068
     9 
    10 >> rand(3,1)
    11 
    12 ans =
    13 
    14     0.4860
    15     0.8913
    16     0.7621
    17 
    18 >> rand('state',0)
    19 >> rand(3,1)
    20 
    21 ans =
    22 
    23     0.9501
    24     0.2311
    25     0.6068

      可以看到,第三次产生随机数,因为初始状态都是0,所以产生了完全一样的随机数!
    设定初始状态的好处是,只需要保存那时的初始状态再运行一遍程序你就可以重现之前的计算过程和结果。

      缺点是虽然程序使用了随机数,但由于(每次启动后)初始状态一样,实际运行出来却是相同的重复过程,你需要人工设定一个保证随机性的初始状态。

    三.问题分析

      计算机系统中的随机数都是伪随机数,是通过一个算法连续产生的,知道上一个随机数,下一个随机数就确定,已知从给定的某个数开始,后面连续的随机数序列都已经确定,我们使用随机数就好像从这个序列中(也叫随机数流)中取数字使用,为了增加随机数的随机程度,和可控性,用rand('state',X)来设置随机数流的状态,就像C语言中随机数的seed,一旦给一个X值,那么后面的随机数流就确定,为了增加随机性,这里用当前时间数码sum(clock)作为随机数的状态,clock返回一个6个元素的向量分辨是年月日时分秒,sum加起来就作为随机数的状态,因为你每次运行程序的时间不同,所以得到的随机数序列就不同单独使用这句时,改变了随机数流的状态,但是还没有使用,所以不产生任何变量。但这个算法有一个问题是,如果计算机太快的话,仍然会生成相同随机数。可考虑用 rand('state',sum(clock)*rand(1))。

    四.问题解决

    4.1 如何设置初始状态

    rand('seed', S) 
    rand('state', S)
    rand('twister', S)
    

      S是表示初始状态的整数。
      seed、state、twister就比较奇怪,令人捉摸不透,不知道该选用哪个。这实际上是产生随机数的不同算法。

      seed表示采用v4版本的随机数产生器,state是v5版本的随机数产生器,最后的twister用的则是Mersenne Twister随机数产生器。

      那么具体该用哪一个呢?在新版本的语法说明中,Matlab给出了答案:前两个随机数产生器都是“flawed”,推荐大家使用twister随机数产生器。

      此外,MathWorks公司意识到了这几个参数可能会产生误导,于是在新版本(2012及以后)的Matlab中更新了语法。

    rng(1);
    A = rand(2,2);
    
    rng('shuffle')
    A = rand(2,2);
    

      新版的Matlab默认采用Mersenne Twister随机数产生器,rng(S) 函数表示设定初始状态,rng('shuffle') 表示随机分配一个初始状态。

      所以现在只需要记住rng()函数设置初始状态,然后用rand产生随机数就可以了。

      然而,有时我们只需要“真正”的伪随机数(不重复!),如何得到?

    4.2 产生非重复随机数

      用2012版本之后的用户比较方便,在产生随机数之前使用rng('shuffle')洗一下就可以(shuffle是洗牌的意思)。

    对于旧版本的用户,还不支持rng函数。以前一般是rand('state',sum(100*clock))来根据当前时间设定初始状态,但时间始终是递增的,而且变化幅度相对来说很小,效果不是很好。

      有很多人用别的方式设定初始状态(如rand('twister', fix(mod(1e11*(sum(clock)-2009), 2^31)));),为简便起见,个人推荐采用新版Matlab中rng函数语法,即rand('twister',mod(floor(now*8640000),2^31-1)) ,这样可以产生的不同的随机数。采用这种办法大约每497天种子才会重复一次,一般使用的话足够了。

      参考文献:百度知道

      http://cn.mathworks.com/help/matlab/math/generate-random-numbers-that-are-different.html

  • 相关阅读:
    Windows 常见错误总结
    Windows 常用快捷方式
    【Linux】wget: command not found的两种解决方法
    【Linux】VirtualBox虚拟网络配置
    【Linux】启动Tomcat遇到Neither the JAVA_HOME nor the JRE_HOME environment variable is defined
    【REDIS】 redis-cli 命令
    【Charles】使用Charles时,抓不到包的情况。
    【Gradle】Downloading https://services.gradle.org/distributions/gradle-3.3-bin.zip 失败
    【LINUX】SHELL syntax error:unexpected end of file
    motan源码分析七:序列化
  • 原文地址:https://www.cnblogs.com/hxsyl/p/4523988.html
Copyright © 2011-2022 走看看