从伪随机数的产生到高大上的蒙特卡洛算法(C语言实现)
来源:互联网 发布:瑞易物管软件 官网 编辑:程序博客网 时间:2024/06/05 01:02
- 一 准备
- 1 生成任意区间任意大小的伪随机数
- 2 什么是蒙特卡洛算法
- 二蒙特卡洛算法的实现
- 1 pi的蒙特卡洛计算方式
- 2 特殊图形的蒙特卡洛计算方式
通过这篇短文想说明两个道理:
- 看似高大上、神秘兮兮的算法,都是paper tiger;
- 计算机的计算方式(动辄几Ghz的主频)简直就是为蒙特卡洛度身定做;
一、 准备
1.1 生成任意区间任意大小的伪随机数
C语言中的
rand()
更深远的意义在于其对应于数学(概率论)中的均匀分布(uniformed distributed)。
C语言生成伪随机数的函数:
int rand(void);
该函数随机生成0~RAND_MAX
之间内的整数:
#define RAND_MAX 0x7fff // 0x7fff == 32767
产生随机数需要设置种子:
void srand(unsigned int _Seed);
这两个函数所在的头文件是stdlib.h
或者cstdlib
,后者又被包含在iostream
头文件中。
有了rand()
这个可以生成0-RAND_MAX
随机数(整数)的函数,经过一定的四则运算和取模运算,便可很容易地得到任意区间的随机数。
以生成(2, 5)
之间的随机数(可整可小)为例:
double x = 3*(double(rand())/RAND_MAX)+2;
先通过double(rand())/RAND_MAX
使随机数区间转换为(0, 1)
,再通过一定的伸缩平移实现对任意区间的仿真,这里的double
类型转换不可省略,否则整数之间的除法运算得到的结果仍是整数。
double
vsfloat
两者的区别在于对浮点数表达的精度不同,double
是双精度,float
为单精度。
sizeof(double) == 8;sizeof(float) == 4;
c语言中的浮点数默认是double
类型的,除非显式声明为l
(或者L
)
float x = 1l;
long
vsint
16位系统:long是4字节,int是2字节
32位系统:long是4字节,int是4字节
64位系统:long是8字节,int是4字节
更详细的讨论见long
vsint
。
更详细的内容参见之前的一篇博客C++伪(pseudo)随机数生成及简单应用。
1.2 什么是蒙特卡洛算法?
这部分内容会比较枯燥,如果读不下去,可先看后边的实验,再读这部分内容会很容易理解和接受。
蒙特卡罗方法(Monte Carlo method),也称统计模拟方法,是一种数值计算方法。是二十世纪四十年代中期由于科学技术的发展和电子计算机
的发明,而被提出的一种以概率统计理论
为指导的一类非常重要的数值计算
方法。是指使用随机数
(或更常见的伪随机数
)来解决很多计算问题的方法。
通常蒙特卡罗方法:因所求解的问题本身具有内在的随机性,借助计算机的运算能力可以直接模拟这种随机的过程。
更详尽的解释,参见Monte Carlo method, 蒙特卡洛算法在机器学习中的应用可参见增强学习-蒙特卡洛方法。
二、蒙特卡洛算法的实现
2.1 π 的蒙特卡洛计算方式
如图所示的正方形其面积
想象这是一张纸,其中的圆弧线,将纸划分为两部分,在下雨时将这张纸放置室外,经过一段时间,雨点落在
可得
可通过对大量重复随机实验来仿真或者近似计算
易写出如下的程序:
#include <stdio.h>#include <stdlib.h>#include <time.h>#include <math.h>int main(int, char**){ long c = 0, d = 0, N = 10000; double x = 0, y = 0, pi = 0; srand(unsigned(time(NULL))); for (long i = 0; i < N; ++i) { d += 1; x = double(rand()) / RAND_MAX; y = double(rand()) / RAND_MAX; if (sqrt(x*x + y*y) <= 1) // x^2表示异或; c += 1; } printf("π= %f\n", 4.*c / d); return 0;}
这里有一份迭代出来的近似值:
可见随着计算迭代次数的增加,估算的精度越来越高。
2.2 特殊图形的蒙特卡洛计算方式
继续沿用计算
- 对圆心在
(0,0) 的扇形而言,
- 对圆心在
(1,0) 的扇形而言,
转化为程序语言即是:
if (sqrt(x*x+y*y)>1 && sqrt((x-1)*(x-1)+y*y)>1) c+=1;
真实的区域面积应当等于:
#include <stdio.h>#include <stdlib.h>#include <time.h>#include <math.h>int main(int, char**){ long c = 0, d = 0, N = 100000; double x = 0, y = 0, pi = 0; srand(unsigned(time(NULL))); for (unsigned i = 0; i < N; ++i) { d += 1; x = double(rand()) / RAND_MAX; y = double(rand()) / RAND_MAX; if (sqrt(x*x + y*y) > 1 && sqrt((x - 1)*(x - 1) + y*y) > 1) c += 1; } printf("s = %f\n", double(c) / d); return 0;}
- 从伪随机数的产生到高大上的蒙特卡洛算法(C语言实现)
- C语言的伪随机数
- C语言之实现随机数产生算法
- C语言随机数的产生
- C语言随机数的产生
- C语言随机数的产生
- C语言生成0到1的伪随机数
- C语言产生一个[M, N]区间上的随机数
- 用C语言的rand()和srand()产生伪随机数的方法总结
- 用C语言的rand()和srand()产生伪随机数的方法总结
- 用C语言的rand()和srand()产生伪随机数的方法总结
- 用C语言的rand()和srand()产生伪随机数的方法总结
- 用C语言的rand()和srand()产生伪随机数的方法总结
- 用C语言的rand()和srand()产生伪随机数的方法总结
- 用C语言的rand()和srand()产生伪随机数的方法总结
- 用C语言的rand()和srand()产生伪随机数的方法总结
- BASE64的伪随机数产生
- 常见的伪随机数产生
- 简单动画的正反播放
- Java基础---网络编程
- android studio编译较大项目时出现问题createDebugMainDexClassList....finished with non-zero exit value x
- 安卓自定义控件初探---仿web验证码的实现
- 秒变专家,三招教你选高品质移动电源
- 从伪随机数的产生到高大上的蒙特卡洛算法(C语言实现)
- IOS-11-关于AFNetworking访问网络超时的设置
- c调用lua函数
- 怎样设置一个适合自己的终端(shell)->zsh 终极cell ->装逼神器
- C#实现对SQL数据库中的表的查询、添加、修改、删除数据
- JSON
- 实现add(2)(3)(4)得出结果为 9
- 传统的项目经理可以担当Scrum Master吗
- 20个你可能不知道的 Linux 网络工具