精华内容
下载资源
问答
  • 乘同余法产生随机数

    2013-07-02 10:29:35
    系统辨识中利用乘同余法产生服从0,1分布的随机数
  • 在用计算机编制程序时,经常需要用到随机数,尤其在仿真等领域,更对随机数的产生提出了较高的要求,仅仅...而用数学方法产生随机数则最适合计算机,这就是周期有限,易重复的“伪随机数”。 (注:这里生成的随机数所
    在用计算机编制程序时,经常需要用到随机数,尤其在仿真等领域,更对随机数的产生提出了较高的要求,仅仅使用 C 语言类库中的随机函数已难以胜任相应的工作。现实中,用投色子计数的方法产生真正的随机数,但电脑若也这样做,将会占用大量内存;虽然用噪声发生器或放射性物质也可产生真正的随机数,但操作不可重复。而用数学方法产生随机数则最适合计算机,这就是周期有限,易重复的“伪随机数”。
    (注:这里生成的随机数所处的分布为 0-1 区间上的均匀分布。不是 0-1 区间怎么办? 除以 (high-low), 再加上 low 就可以完成任务。我们需要的随机数序列应具有非退化性,周期长,相关系数小等优点。)
     
    1、迭代取中法:
    这里在迭代取中法中介绍平方取中法 , 其迭代式如下 : 
                      Xn+1=(Xn^2/10^s)(mod 10^2s) 
                      Rn+1=Xn+1/10^2s

    其中,Xn+1是迭代算子,而 Rn+1 则是每次需要产生的随机数。 
    第一个式子表示的是将 Xn 平方后右移 s 位,并截右端的 2s 位。 
    而第二个式子则是将截尾后的数字再压缩 2s 倍,显然 :0=<Rn+1<=1。
    迭代取中法有一个显著的不良特性就是它比较容易退化成 0。
     
    实现代码(C语言):
    #include <stdio.h>
    #include <math.h>
    #define S 2
     
    float Xn=12345;  //Seed & Iter
    float Rn;        //Return Val
     
    void InitSeed(float inX0)
    {
          Xn=inX0;
    }
     
    float MyRnd()
    {
          //implementation: Xn+1=(Xn^2/10^S)(mod 10^2S)
          Xn=(int)fmod((Xn*Xn/pow(10,S)),pow(10,2*S));//here can's use %
          
          //implementation: Rn+1=Xn+1/10^2S
          Rn=Xn/pow(10,2*S);
     
          return Rn;
    }
     


    /*测试主程序,注意,本文只列举一次测试主程序,以下不再重复*/
    int main()
    {
         int i;
         FILE * debugFile;
         if((debugFile=fopen("outputData.txt","w"))==NULL)
         {
              fprintf(stderr,"open file error!");
              return -1;
         }   
         printf("\n");
         for(i=0;i<100;i++)
         {
              tempRnd=MyRnd();
              fprintf(stdout,"%f ",tempRnd);
              fprintf(debugFile,"%f ",tempRnd);
         }                  
         getchar(); 
         return 0;
    }


     

    前一百个测试生成的随机数序列(明显可见其容易退化为0):

    0.399000 0.920100 0.658400 0.349000 0.180100 0.243600 0.934000 0.235600 0.550700 0.327000 0.692900 0.011000 0.012100 0.014600 0.021300 0.045300 0.205200 0.210700 0.439400 0.307200 0.437100 0.105600 0.115100 0.324800 0.549500 0.195000 0.802500 0.400600 0.048000 0.230400 0.308400 0.511000 0.112100 0.256600 0.584300 0.140600 0.976800 0.413800 0.123000 0.512900 0.306600 0.400300 0.024000 0.057600 0.331700 0.002400 0.000500 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000

     

    2、乘同余法:

    乘同余法的迭代式如下:

                                             Xn+1=Lamda*Xn(mod M)

                                             Rn+1=Xn/M

           当然,这里的参数选取是有一定理论基础的,否则所产生的随机数的周期将较小,相关性会较大。经过前人检验的两组性能较好的素数取模乘同余法迭代式的系数为:

                                            Lamda=5^5,M=2^35-31

                                            Lamda=7^5,M=2^31-1

    实现代码(C语言)关键部分:

    double long  M;//请注意,这里一定要用到double long,否则计算2^32会溢出
    float MyRnd()
    {
                  Xn=fmod(Lamda*Xn,M);//here can's use %
                  Rn=Xn/M;
                  return Rn;
    }
     
    另外初始化段应有:
    Lamda=pow(5,5);
    M=pow(2,35)-31;


     

     

    前三百个测试生成的随机数序列(可见该随机数生成方法所生成的随机序列比较符合0-1上的均匀分布,不过在某些数据段还有些起伏):

    图1:  乘同余法生成的300随机数的产生序列图

     

     

     2: 乘同余法生成的300随机数的分布情况
     
    3、混合同余法:
    混合同余法是加同余法和乘同余法的混合形式,其迭代式如下:
                    Xn+1=(Lamda*Xn+Miu)%M
                    Rn+1=Xn/M
    经前人研究表明,在M=2^q的条件下,参数lamda,miu,X0按如下选取,周期较大,概率统计特性好:
                    Lamda=2^c+1,c取q/2附近的数
                    Miu=(1/2+sqrt(3))/M
                    X0为任意非负整数
          
    实现代码(C语言)关键部分:
    float MyRnd()
    {
        Xn=fmod(Lamda*Xn+Miu,M);
        Rn=Xn/M;
        return Rn;
    }
     
    另外初始化段应有:
    M=pow(2,32);
    Lamda=pow(2,16)+1;
    Miu=(0.5+sqrt(3)/6)/M;


     
    前三百个测试生成的随机数序列(可见该种随机数生成方法已相当接近0-1上的均匀分布。但在图3中可以看出它的一个致命的弱点,那就是随机数的生成在某一周期内成线性增长的趋势,显然,在大多数场合,这种极富“规律”型的随机数是不应当使用的。):
    图3: 乘同余法生成的300随机数的产生序列图
    图4: 乘同余法生成的300随机数的分布情况
    展开全文
  • 一、概念混合同余法:用一常数与已产生的伪随机数之积的同余式做递推公式,产生均匀伪随机数的方法。即:第一步:递推式其中:M=2^k,k>2整数;A=1(mod4),即为正整数,初值x*0为非负整数。第二步:可以证明,是周期...

    一、

    概念

    混合同余法

    用一常数与已产生的伪随机数之积的同余式做递推公式

    ,

    产生均匀伪随机数的方法。

    即:

    第一步:递推式

    其中:

    M=2^k,k>2

    整数;

    A=1(mod4),

    为正整数

    ,

    初值

    x

    *

    0

    为非负整数。

    第二步:

    可以证明,

    是周期为

    2k

    的伪随机数。

    1

    、混合同余法(

    0

    1

    )均匀分布的随机数

    L=60,

    k=2,c=1,n=5,l=60,

    x

    *

    0

    =1

    公式原理:

    见上第一第二步。

    程序:

    clear

    clc

    k=8;

    c=1;

    n=5;

    x=1;

    M=2^k;

    A=2^n+1;

    store=[ ];

    for i=1:60

    ee=x/M;

    store(i)=ee;

    x=mod(A*x+c,M);

    end

    plot(1:60,store)

    title('

    混合同余法产生随机数

    ')

    store=

    0.00390625000000000

    0.132812500000000

    0.386718750000000

    0.765625000000000

    0.269531250000000

    0.898437500000000

    0.652343750000000

    0.531250000000000

    0.535156250000000

    0.664062500000000

    0.917968750000000

    0.296875000000000

    0.800781250000000

    0.429687500000000

    0.183593750000000

    0.0625000000000000

    0.0664062500000000

    0.195312500000000

    0.449218750000000

    0.828125000000000

    0.332031250000000

    0.960937500000000

    0.714843750000000

    0.593750000000000

    0.597656250000000

    0.726562500000000

    0.980468750000000

    0.359375000000000

    0.863281250000000

    0.492187500000000

    3

    ,

    2

    ,

    1

    ),

    (m

    od

    1

    i

    M

    c

    Ax

    x

    i

    i

    3

    4

    2

    ,

    1

    2

    n

    A

    展开全文
  • 乘同余法产生(0,1)均匀分布随机数的matlab代码,可在此基础上改进为不同分布的随机数,调试通过的
  • 乘同余法

    2021-02-20 00:53:09
    乘同余法 概述 该方法用于产生(0,1]之间的随机数,计算公式如下: xi=(Axi−1)(ModM)ri=xi/M x_i=(Ax_{i-1})(Mod M)\\ r_i=x_i/M xi​=(Axi−1​)(ModM)ri​=xi​/M 实现 c++实现代码如下: #include<iostream>...

    乘同余法

    概述

    该方法用于产生(0,1]之间的随机数,计算公式如下:
    xi=(Axi1)(ModM)ri=xi/M x_i=(Ax_{i-1})(Mod M)\\ r_i=x_i/M

    实现

    c++实现代码如下:

    #include<iostream>
    #include<math.h>
    using namespace std;
    int main()
    {
      int n;
      cout<<"伪随机数个数:"<<endl;
      cin>>n;
      int number[n];
      double pse_number[n];
      number[0]=1;
      int A=3,M=16;
      for(int i=1;i<n;i++)
      {
          number[i]=(A*number[i-1])%M;
      }
      for(int i=0;i<n;i++)
      {
           pse_number[i]=float(number[i])/float(M);
      }
      for(int i=0;i<n;i++)
      {
          cout<<pse_number[i]<<endl;
      }
      return 0;
    }
    

    matlab代码如下:

    //randon.m
    function [xx,rr]=randon(x,r,A,M,n)
    x(1)=1;
    for i = 1:n
           x(i+1)=mod((x(i)*A),M);
    end
    for i = 1:n
           r(i)=x(i)/M;
    end
    
    //主程序
    x=[]
    r=[]
    [x,r]=randon(x,r,1001,999988,1000)
    plot(r)
    

    检验

    A=101 M=97 n=1000

    yluFaT.png

    A=1001 M=999988 n=1000

    ylukIU.png

    展开全文
  • 在新算法中,以原线性乘同余发生器中的模数为基础,通过相同种子数平均分配构造产生随机数;由于算法分段实现,使得随机数的产生在计算量上不会有明显的增加,能满足购车摇号所需。统计检验结果表明,该算法对随机...
  • Matlab随机数生成

    2020-11-08 20:47:08
    Matlab随机数生成的常用算法实现(用平方取中法产生随机数列 、用混合同余法产生随机数列 、用乘同余法1产生随机数列 、产生柯西分布的随机数列 、产生正态分布的随机数列 、产生贝努里-高斯分布的随机数列 )
  • 随机数就是随机产生的数-_-||,分为两种:真随机数(random number)和伪随机数(pseudo-random number)。自然界由很多复杂因素产生的现象量化后的数(比如掷骰子)是真正随机的,就是真随机数。 一般意义上的电子...

    随机数就是随机产生的数-_-||,分为两种:真随机数(random number)和伪随机数(pseudo-random number)。自然界由很多复杂因素产生的现象量化后的数(比如掷骰子)是真正随机的,就是真随机数。

    一般意义上的电子计算机是确定系统,常规方法无法产生真随机数,而且真随机数的统计指标(原点矩、方差等)不一定好,且无法“重现”,故计算机常用伪随机数,又称为伪随机序列(pseudo-random sequence)。


    /***************************加乘混合同余法****************************/


    伪随机序列生成法有很多种,有取中法、移位法、同余法,近年来还有Gold序列(用于LTE系统加密)等等。

    一般来说,伪随机序列常用[0,1]上的均匀分布,需要其他分布时,可以用概率积分变换快速地转换为其他分布

    其中,生成算法比较简单,性能也比较高的算法是同余法中的加乘混合同余法,其公式表示为:

    R_n+1 =k R_n +C (mod M) 

    其中C和 λ为常数,且C不为0, λ不为1(C=0是乘法同余法,λ=1是加法同余法)。

    由于要得到[0,1]上的序列,于是

    以下不加证明(其实是我没找到,求高手给证明)地给出随机序列周期达到M的充要条件为:

    1 )c 与M 互素;

    2 ) 对每一个M 的素因子p ,λ - 1为p 的倍数;

    3 ) 若M 是4 的倍数,那么λ- 1 是4 的
    倍数.

    由以上条件易知,在2 进制计算机上,若,应取λ =4q + 1 ,c = 2 a + 1 ,为任意非负整数,其中q,a为正整数.

    它的一个致命的弱点,那就是随机数的生成在某一周期内成线性增长的趋势,显然,在大多数场合,这种极富“规律”型的随机数是不应当使用的。


    /****************随机序列质量的衡量指标***************************/

    1、均匀性

    比如以0.5为界,左右两边应几乎各占一半

    2、覆盖性

    对模拟需要的值,应几乎全部取到,不应有遗漏

    3、循环性

    不论序列有多长,应构成一个首尾相连的闭环序列

    4、非循环性

    这个意思是说“循环要足够长”,之前说循环性是指“能回来”,这里指“不能还没模拟完就回来”

    5、独立性

    随机序列应只取决于随机生成算法

    6、检验性

    随机函数要能经得起各种统计检验

    7、系统开销要小

    这个是大多数程序要求的,时间复杂度和空间复杂度要尽量低。

    /*************蒙特卡罗方法*************************************/

    Monte Carlo 方法的要点是:对要解决的数值计算问题,构造适当的概率模型,使要得到的解正好
    重合于概率模型中随机变量的概率分布或数字特征,其后在计算机上用伪随


    机数列对随机变量进行模拟得到一个大子样的观测数据,进行统计整理以后,给出问题的一个近似估计. 因此,Monte Carlo方法是双重近似,一是将数值计算问题用概率模型作近似,二是在计算机上用伪随机数作近似抽样值进行统计整理作出一些估计.

    设g ( x ) 是[0 ,1 ] 上的连续函数, 且0 ≤ g ( x )≤1 . 考虑定定积分


    的值,那么由y=g(x)、y=0、x=0、x=1围成的图形面积就是S,如果在单位正方形(0,0,1,1)内均匀地投点(x , y ) ,则该随机点落入曲线y = g ( x ) 下阴影的概率:


    向正方形0 ≤x ≤1 ,0 ≤y ≤1 内均匀投点   ,ξi ,ηi 是相互独立的均匀随机数列,第i 次试验成
    功,即 落入A 中,也就是满足ηi ≤g (ξi ) ,若每次成功的概率为p ,进行n 次试验成功了k 次,则由大数定理知

    即n 充分大时, k/ n 依概率收敛到p . 由于p = s ,因此常取s ≈ k/ n .

    于是,一个伪随机序列的质量可以用蒙特卡罗方法验证

     

    /*****************翠花,上代码*********************************/

    我们取

    $M=2^30=1073741824$

    $\lambda=129$

    C=129

    写的比较难看,大家凑合看一下吧……

     

    ExpandedBlockStart.gifC++代码
    1 #include <iostream>
    2  #define M 1073741824
    3  #define K 129
    4  #define C 17
    5  #define N 100000
    6  const int n=3;
    7  using namespace std;
    8  long long t;
    9
    10  /**********加乘混合同余法**************/
    11  double rand(){
    12 double x;
    13 t=(K*t+C)%M;//t=Kt+c (mod M)
    14   x=double(t)/M;
    15 return x;
    16 }
    17
    18  /*************乘方计算****************/
    19  long double power(long double x,long double n){
    20 long double y=x;
    21 for(int i=1;i<n;i++)
    22 y*=x;
    23 return y;
    24 }
    25
    26  /*********** 蒙特卡罗积分法 *********/
    27  long double integrate(long double x[],long double y[]){
    28 long double s;
    29 long k=0;
    30 for(int i=0;i<N;i++){
    31 if(y[i]<=power(x[i],n))
    32 k++;
    33 }
    34 s=(long double)k/N;
    35 return s;
    36 }
    37
    38  int main(){
    39 long double x[N],y[N],s=0.0,s2=0.0,d,e;
    40 int i;
    41 t=124;
    42 for(i=0;i<N;i++){
    43 x[i]=rand();
    44 s=s+x[i];//累加
    45 cout<<x[i]<<endl;
    46 }
    47 t=54;
    48 for(i=0;i<N;i++){
    49 y[i]=rand();
    50 }
    51 e=s/N;//平均数
    52 for(i=0;i<N;i++){
    53 s2+=(x[i]-e)*(x[i]-e);
    54 d=s2/(N-1);//方差 dafdq
    55 }
    56 cout<<"The average is "<<e
    57 <<",which is 0.5 theoretically"<<endl<<endl;
    58 cout<<"The mean square deviation is "<<d
    59 <<",which is 0.08333333 theoretically"<<endl<<endl;
    60 cout<<"Intgreate resault is "<<integrate(x,y)
    61 <<",which is "<<(double)1/(n+1)<< " theoretically"<<endl<<endl;
    62 return 0;
    63 }

     



     

     

     给结果(序列太长了,略去)

    The average is 0.500178,which is 0.5 theoretically

    The mean square deviation is 0.0833717,which is 0.08333333 theoretically

    Integreate result is 0.24989,which is 0.25 theoretically

     

    %%%%%%%%%%%%Matlab程序%%%%%%%%%%%%%%%%%%%%%

     

    用matlab测试的时候发现,先前选取的λ=65537并不好,在N=1000时,产生的序列是这样的


    一块一块的很难看,

    把N降到一百

    非常明显的线性,这个缺点很大了!

    所以我换了参数,并且与matlab自带的rand()进行了比较

     

    clear;
    M
    =2^32;
    k
    =129;
    C
    =53;
    x(
    1)=63343;
    r(
    1)=63343/M;
    n
    =1000;
    m
    =rand(n,1);
    for i=2:n
    x(i)
    =mod(k*x(i-1)+C,M);
    r(i)
    =x(i)/M;

    end
    i
    =1:n;
    subplot(
    311)
    plot(i,r,
    '-r')
    subplot(312)
    plot(i,m,
    '-g');
    b=fft(r);
    c
    =abs(b);
    c(
    1)=0; %0点有bug
    subplot(
    313)
    plot(c);

     

     





    其中绿色的是matlab自带函数生成的序列,蓝色的是频谱图

    *参考文献


    [1] 郭继展 过勇 苏辉 . 程序算法与技巧精选 ,机械工业出版社,2008

    [2]郑 列, 宋正义 伪随机数生成算法及比较 ,湖北工业大学学报,2008 年10 月

    转载于:https://www.cnblogs.com/justin-wong/archive/2010/01/30/1660226.html

    展开全文
  •  本文简述了随机数产生原理,并用C语言实现了迭代取中法,乘同余法随机数产生方法,同时,还给出了在符合某种概率分布的随机变量的产生方法。   关键词: 伪随机数产生,概率分布   1前言:  在用计算机...
  •  本文简述了随机数产生原理,并用C语言实现了迭代取中法,乘同余法随机数产生方法,同时,还给出了在符合某种概率分布的随机变量的产生方法。 关键词: 伪随机数产生,概率分布 1前言:  在用计算机编制程序...
  • 本文简述了随机数产生原理,并用C语言实现了迭代取中法,乘同余法随机数产生方法,同时,还给出了在符合某种概率分布的随机变量的产生方法。 关键词: 伪随机数产生,概率分布 1前言: 在用计算机编制...
  • 随机数产生原理 - C语言实验篇

    千次阅读 2012-09-25 21:17:41
     本文简述了随机数产生原理,并用C语言实现了迭代取中法,乘同余法随机数产生方法,同时,还给出了在符合某种概率分布的随机变量的产生方法。   关键词: 伪随机数产生,概率分布   1前言:  在用计算机...
  • [zz]各种随机数产生

    千次阅读 2007-10-16 22:13:00
    摘要 : 本文简述了随机数产生原理,并用 C 语言实现了迭代取中法,乘同余法随机数产生方法,同时,还给出了在符合某种概率分布的随机变量的产生方法。关键词 : 伪随机数产生,概率分布 , 正态随机数 , 泊松...
  • 今天,利用MATLAB编写乘同余法产生随机数相关代码时,遇到一个问题: (下图仅截取部分代码片段) a=6/256 b=6; c=a*b 输出结果为: 再次运算: d=0.0234*6 发现: 二者显然不相同。但是他们似乎是用相同的数0....
  • 用java语言产生符合泊松分布的随机数...同余法是Lehmer于1951年提出来的此方法是利用数论中的同余运算原理来产生随机数有线性同余法非线性同余法等其中线性同余法法又分为加同余法乘同余法以及混合同余法同余法是现在发
  • 随机函数的底层深入探究

    千次阅读 2014-05-08 02:26:02
     本文简述了随机数产生原理,并用C语言实现了迭代取中法,乘同余法随机数产生方法,同时,还给出了在符合某种概率分布的随机变量的产生方法。 关键词: 伪随机数产生,概率分布 1前言:  在用计算机...
  • 这一章通过猜拳游戏来讲解计算机的功能,计算机本身不具有思考的功能,是通过人的思想通过程序来使其计算机具有高于人的精确计算的...除此之外还有线性同余法、乘同余法、M系法、Knuth减算法。Stand(time(null))是根...
  • 一.原理: C语言中伪随机数生成算法实际上是采用了"线性同...当C=0时,叫做乘同余法。 假设我们定义随机数函数: void rand(int &seed) { seed = (seed * A + C ) % M; }每次调用rand函数都会产生一个随机值赋值给
  • 用线性同余法生成随机数序列的公式为: r_k = (multiplier * r_k-1 + increment) % modulus 序列中的每个数r_k都可以由它的前一个数r_k-1计算出来。例如,如果有: r_k = (25173 * r_k-1 + 13849) % 65536 则可以...
  • MATLAB语言常用算法程序集

    热门讨论 2009-07-19 20:28:29
    PrimeMOD 用素数模同余法产生随机数列 PowerDist 产生指数分布的随机数列 LaplaceDist 产生拉普拉斯分布的随机数列 RelayDist 产生瑞利分布的随机数列 CauthyDist 产生柯西分布的随机数列 AELDist 产生爱尔朗分布的...
  • MATLAB常用算法

    热门讨论 2010-04-05 10:34:28
    PrimeMOD 用素数模同余法产生随机数列 PowerDist 产生指数分布的随机数列 LaplaceDist 产生拉普拉斯分布的随机数列 RelayDist 产生瑞利分布的随机数列 CauthyDist 产生柯西分布的随机数列 AELDist 产生爱尔朗分布的...

空空如也

空空如也

1 2
收藏数 26
精华内容 10
关键字:

乘同余法产生随机数