随机化算法(1) — 随机数

最近在看王晓东的《计算机算法设计与分析(第3版) 》,感觉讲的挺不错的。这里先推荐下。

接下来的几章(包括本章),我准备以连载的方式讲出来,主要用到的资料是上面推荐的那本书以及《算法导论》和网上的资源,内容是概率分析与随机算法。文章内大部分内容出自书中,我仅以汇总形式以及个人理解加以补充。如有纰漏,欢迎指出。

概率算法的一个基本特征是对所求解问题的同一实例用同一概率算法求解两次可能得到完全不同的效果。这两次求解问题所需的时间甚至所得到的结果可能会有相当大的差别。一般情况下,可将概率算法大致分为四类:数值概率算法,蒙特卡罗(Monte Carlo)算法,拉斯维加斯(Las Vegas)算法和舍伍德(Sherwood)算法。

随机数在概率算法设计中扮演着十分重要的角色。在现实计算机上无法产生真正的随机数,因此在概率算法中使用的随机数都是一定程度上随机的,即伪随机数

产生随机数最常用的方法是线性同余法。由线性同余法产生的随机序列a1,a2,…,an满足
1.a0=d
2.an=(b*an-1+c)mod m (n=1,2…….)
其中,b>0, c>=0, d>=m。d称为该随机序列的种子

一般情况下,取gcd(m, b)=1,因此可取b为一素数。

 

这是一个随机数类

《随机化算法(1) — 随机数》
《随机化算法(1) — 随机数》
代码
const
 unsigned 
long
 maxshort 
=
 
65535L
;

const
 unsigned 
long
 multiplier 
=
 
1194211693L
;

const
 unsigned 
long
 adder 
=
 
12345L
;
 

class
 RandomNumber{

private
:
    

//
 当前种子


    unsigned 
long
 randSeed;

public
:
    

//
 构造函数,默认值0表示由系统自动产生种子


    RandomNumber(unsigned 
long
 s 
=
 
0
);
    

//
 产生0 ~ n-1之间的随机整数


    unsigned 
short
 Random(unsigned 
long
 n);
    

//
 产生[0, 1) 之间的随机实数


    
double
 fRandom();
};
 

//
 产生种子


RandomNumber::RandomNumber(unsigned 
long
 s)
{
    

if
(s 
==
 
0
)
        randSeed 

=
 time(
0
);    
//
用系统时间产生种子


    
else

        randSeed 

=
 s;
}
 

//
 产生0 ~ n-1 之间的随机整数


unsigned 
short
 RandomNumber::Random(unsigned 
long
 n)
{
    randSeed 

=
 multiplier 
*
 randSeed 
+
 adder;
    

return
 (unsigned 
short
)((randSeed 
>>
 
16

%
 n);
}
 

//
 产生[0, 1)之间的随机实数


double
 RandomNumber::fRandom()
{
    

return
 Random(maxshort) 
/
 
double
(maxshort);
}

 

 利用这个随机数类,写一个程序,模拟抛硬币的实验。

抛10次硬币构成一个事件,每次事件记录得到正面的个数。反复模拟这个事件50,000次,然后对这50,000L次进行输出频率图,比较每次事件得到正面次数的比例。

以下是总的代码:
头文件 RandomNumber.h:

《随机化算法(1) — 随机数》
《随机化算法(1) — 随机数》
代码
//
 RandomNumber.h


 

const
 unsigned 
long
 maxshort 
=
 
65535L
;

const
 unsigned 
long
 multiplier 
=
 
1194211693L
;

const
 unsigned 
long
 adder 
=
 
12345L
;
 
#ifndef RANDOMNUMBER_H

#define
 RANDOMNUMBER_H

 

class
 RandomNumber{

private
:
    

//
 当前种子


    unsigned 
long
 randSeed;

public
:
    

//
 构造函数,默认值0表示由系统自动产生种子


    RandomNumber(unsigned 
long
 s 
=
 
0
);
    

//
 产生0 ~ n-1之间的随机整数


    unsigned 
short
 Random(unsigned 
long
 n);
    

//
 产生[0, 1) 之间的随机实数


    
double
 fRandom();
};
 

#endif

 

 类实现文件RandomNumber.cpp : 

 《随机化算法(1) — 随机数》代码

//
 RandomNumber.cpp


#include 

RandomNumber.h


#include 

<
iostream
>

#include 

<
stdlib.h
>

#include 

<
time.h
>

 

using
 
namespace
 std;
 

//
 产生种子


RandomNumber::RandomNumber(unsigned 
long
 s)
{
    

if
(s 
==
 
0
)
        randSeed 

=
 time(
0
);    
//
用系统时间产生种子


    
else

        randSeed 

=
 s;
}
 

//
 产生0 ~ n-1 之间的随机整数


unsigned 
short
 RandomNumber::Random(unsigned 
long
 n)
{
    randSeed 

=
 multiplier 
*
 randSeed 
+
 adder;
    

return
 (unsigned 
short
)((randSeed 
>>
 
16

%
 n);
}
 

//
 产生[0, 1)之间的随机实数


double
 RandomNumber::fRandom()
{
    

return
 Random(maxshort) 
/
 
double
(maxshort);
}

 

 主文件Main : 

 《随机化算法(1) — 随机数》代码

//
 主文件main

/*


* Author: Tanky woo
* Blog:   www.WuTianQi.com
* Date:   2010.12.7
* 代码来至王晓东《计算机算法设计与分析》

*/

#include 


RandomNumber.h


#include 

<
iostream
>

#include 

<
iomanip
>

#include 

<
time.h
>


using
 
namespace
 std;
 

int
 TossCoins(
int
 numberCoins)
{
    

//
 随机抛硬币


    
static
 RandomNumber coinToss;
    

int
 i, tosses 
=
 
0
;
    

for
(i 
=
 
0
; i 
<
 numberCoins; 
++
i)
        tosses 

+=
 coinToss.Random(
2
);
    

return
 tosses;
}
 

int
 main()
{
    

//
 模拟随机抛硬币事件


    
const
 
int
 NCOINS 
=
 
10
;
    

const
 
long
 NTOSSES 
=
 
50000L
;
    

//
 heads[i]得到的i次正面的次数


    
long
 i, heads[NCOINS
+
1
];
    

int
 j, position;
    

//
 初始化数组heads


    
for
(j 
=
 
0
; j 
<
 NCOINS
+
1

++
j)
        heads[j] 

=
 
0
;
    

//
 重复50,000次模拟事件


    
for
(i 
=
 
0
; i 
<
 NTOSSES; 
++
i)
        heads[TossCoins(NCOINS)] 

++
;
    

//
 输出频率图


    
for
(i 
=
 
0
; i 
<=
 NCOINS; 
++
i)
    {
        position 

=
 
int
 (
float
(heads[i]) 
/
 NTOSSES
*
72
);
        cout 

<<
 setw(
6

<<
 i 
<<
 

 

;
        

for
(j 
=
 
0
; j
<
position

1

++
j)
            cout 

<<
 

 

;
        cout 

<<
 

*

 
<<
 endl;
    }
    

return
 
0
;
}  

 输出频率图:

《随机化算法(1) — 随机数》

 具体可以看看王晓东的《计算机算法设计与分析》第七章。

下一篇我会写《随机化算法(2) — 数值概率算法》。

 Tanky Woo原创,欢迎转载,转载请附上链接,请不要私自删除文章内任何关于本博客的链接。 

    原文作者:随机数生成算法
    原文地址: https://www.cnblogs.com/tanky_woo/archive/2010/12/10/1901780.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞