任意分布的随机数的产生方法

article/2025/11/10 23:52:41

摘要:
    随机数在实际运用中非常之多,如游戏设计,信号处理,通常我们很容易得到平均分布的随机数。但如何根据平均分布的随机数进而产生其它分布的随机数呢?本文提出了一种基于几何直观面积的方法,以正态分布随机数的产生为例讨论了任意分布的随机数的产生方法。
正文:
一、平均分布随机数的产生
    大家都知道,随机数在各个方面都有很大的作用,在vc的环境下,为我们提供了库函数rand()来产生一个随机的整数。该随机数是平均在0~RAND_MAX之间平均分布的,RAND_MAX是一个常量,在VC6.0环境下是这样定义的:

#define RAND_MAX 0x7fff


   它是一个short 型数据的最大值,如果要产生一个浮点型的随机数,可以将rand()/1000.0这样就得到一个0~32.767之间平均分布的随机浮点数。如果要使得范围大一点,那么可以通过产生几个随机数的线性组合来实现任意范围内的平均分布的随机数。例如要产生-1000~1000之间的精度为四位小数的平均分布的随机数可以这样来实现。先产生一个0到10000之间的随机整数。方法如下 :

int a = rand()%10000;


然后保留四位小数产生0~1之间的随机小数:

double b = (double)a/10000.0;


然后通过线性组合就可以实现任意范围内的随机数的产生,要实现-1000~1000内的平均分布的随机数可以这样做:

double dValue = (rand()%10000)/10000.0*1000-(rand()%10000)/10000.0*1000;


则dValue就是所要的值。
   到现在为止,你或许以为一切工作都已经完成了,其实不然,仔细一看,你会发现有问题的,上面的式子化简后就变为:

double dValue = (rand()%10000)/10.0-(rand()%10000)/10.0;


   这样一来,产生的随机数范围是正确的,但是精度不正确了,变成了只有一位正确的小数的随机数了,后面三位的小数都是零,显然不是我们要求的,什么原因呢,又怎么办呢。
   先找原因,rand()产生的随机数分辨率为32767,两个就是65534,而经过求余后分辨度还要减小为10000,两个就是20000而要求的分辨率为1000*10000*2=20000000,显然远远不够。下面提供的方法可以实现正确的结果:

double a = (rand()%10000) * (rand()%1000)/10000.0;
double b = (rand()%10000) * (rand()%1000)/10000.0;
double dValue = a-b;


   则dValue就是所要求的结果。在下面的函数中可以实现产生一个在一个区间之内的平均分布的随机数,精度是4位小数。

double AverageRandom(double min,double max)
{
int minInteger = (int)(min*10000);
int maxInteger = (int)(max*10000);
int randInteger = rand()*rand();
int diffInteger = maxInteger - minInteger;
int resultInteger = randInteger % diffInteger + minInteger;
return resultInteger/10000.0;
}


   但是有一个值得注意的问题,随机数的产生需要有一个随机的种子,因为用计算机产生的随机数是通过递推的方法得来的,必须有一个初始值,也就是通常所说的随机种子,如果不对随机种子进行初始化,那么计算机有一个确省的随机种子,这样每次递推的结果就完全相同了,因此需要在每次程序运行时对随机种子进行初始化,在vc中的方法是调用srand(int)这个函数,其参数就是随机种子,但是如果给一个常量,则得到的随机序列就完全相同了,因此可以使用系统的时间来作为随机种子,因为系统时间可以保证它的随机性。
   调用方法是srand(GetTickCount()),但是又不能在每次调用rand()的时候都用srand(GetTickCount())来初始化,因为现在计算机运行时间比较快,当连续调用rand()时,系统的时间还没有更新,所以得到的随机种子在一段时间内是完全相同的,因此一般只在进行一次大批随机数产生之前进行一次随机种子的初始化。下面的代码产生了400个在-1~1之间的平均分布的随机数。

double dValue[400];
srand(GetTickCount());
for(int i= 0;i < 400; i++)
{
double dValue[i] = AverageRandom(-1,1);
}


用该方法产生的随机数运行结果如图1所示:

图1 400个-1~1之间平均分布的随机数
二、任意分布随机数的产生
   下面提出了一种已知概率密度函数的分布的随机数的产生方法,以典型的正态分布为例来说名任意分布的随机数的产生方法。
   如果一个随机数序列服从一维正态分布,那么它有有如下的概率密度函数:
(1-1)
其中μ,σ( >0)为常数,它们分别为数学期望和均方差,如果读者对数学期望和均方差的概念还不大清楚,请查阅有关概率论的书。如果取μ =0,σ =0.2,则其曲线为

图2 正态分布的概率密度函数曲线
   从图中可以看出,在μ附近的概率密度大,远离μ的地方概率密度小,我们要产生的随机数要服从这种分布,就是要使产生的随机数在μ附近的概率要大,远离μ处小,怎样保证这一点呢,可以采用如下的方法:在图2的大矩形中随机产生点,这些点是平均分布的,如果产生的点落在概率密度曲线的下方,则认为产生的点是符合要求的,将它们保留,如果在概率密度曲线的上方,则认为这些点不合格,将它们去处。如果随机产生了一大批在整个矩形中均匀分布的点,那么被保留下来的点的横坐标就服从了正态分布。可以设想,由于在μ处的f(x)的值比较大,理所当然的在μ附近的点个数要多,远离μ处的少,这从面积上就可以看出来。我们要产生的随机数就是这里的横坐标。
   基于以上思想,我们可以用程序实现在一定范围内服从正态分布的随机数。程序如下:
double Normal(double x,double miu,double sigma) //概率密度函数
{
return 1.0/sqrt(2*PI*sigma) * exp(-1*(x-miu)*(x-miu)/(2*sigma*sigma));
}
double NormalRandom(double miu,
double sigma,double min,double max)//产生正态分布随机数
{
double x;
double dScope;
double y;
do
{
x = AverageRandom(min,max);
y = Normal(dResult, miu, sigma);
dScope = AverageRandom(0, Normal(miu,miu,sigma));
}while( dScope > y);
return x;
}
参数说明:double miu:μ,正态函数的数学期望
                  double sigma:σ,正态函数的均方差
                  double min,double max,表明产生的随机数的范围
用如上方法,取 μ=0,σ=0.2,范围是-1~1产生400个正态随机数如图3所示:

 图3 μ=0, σ=0.2,范围在-1~1时的400个正态分布的随机数分布图
取 μ=0, σ=0.05,范围是-1~1产生400个正态随机数如图4所示:


图4 μ=0,σ=0.05,范围在-1~1时的400个正态分布的随机数分布图
从图3和图4的比较可以看出, 越小,产生的随机数靠近 的数量越多,也说明了产生的随机数靠近 的概率越大。
我们,先产生4000个在0到4之间的正态分布的随机数,取μ=0,σ=0.2,再把产生的数据的数量做个统计,画成曲线,如下图5所示:

图5 μ=0, σ=0.2,范围在0~4时的4000个正态分布的随机数统计图
从图5中也可以看出,在靠近 处的产生的个数多,远离 处的产生的数量少,该图的轮廓线和概率密度曲线的形状刚好吻合。也就验证了该方法的正确性。
有了以上基础,也就用同样的方法,只要知道概率密度函数,也就不难产生任意分布的随机数,方法都是先产生一个点,然后进行取舍,落在概率密度曲线下方的点就满足要求,取其横坐标就是所要获取的随机数。


http://chatgpt.dhexx.cn/article/PkmvUHPj.shtml

相关文章

如何用均匀分布随机数生成正态分布随机数

文章目录 前言The Box–Muller transformThe Ziggurat algorithm(金字形神塔)附录&#xff1a;Inverse transform sampling直观解释 前言 在Monte Carlo模拟技术中&#xff0c;许多地方都需要用到符合标准正态分布(高斯)的随机数来设计采样方案&#xff0c;因此了解如何用均匀…

常见的概率分布并生成随机数

一、均匀分布&#xff08;Uniform Distribution&#xff09; 在相同长度间隔的分布概率是等可能的。 1.概率密度函数&#xff1a; 2.分布函数&#xff1a; 3.期望和方差&#xff1a; 4.生成随机数 import numpy as np #生成从0-1的均匀分布 np.random.rand(10)#生成十个均匀…

生成特定分布随机数的方法

生成随机数是程序设计里常见的需求。一般的编程语言都会自带一个随机数生成函数&#xff0c;用于生成服从均匀分布的随机数。不过有时需要生成服从其它分布的随机数&#xff0c;例如高斯分布或指数分布等。有些编程语言已经有比较完善的实现&#xff0c;例如Python的NumPy。这篇…

推导:通过均匀分布来产生任意分布随机数

最近想用C语言写一个产生服从指数分布的随机数的程序。从网上找了找&#xff0c;发现可以通过均匀分布来产生服从任意分布的随机数。然而&#xff0c;网上的推导不是很完善&#xff0c;我把自己的理解写在这里&#xff0c;有不严谨的地方请大家指正。 命题1&#xff1a;对一连续…

随机数生成(一):均匀分布

引言 许多应用中都需要用到随机数&#xff0c;如物理仿真、统计采样、密码学、博彩等。随机数一般可以通过两种方法得到。一种是基于物理现象由硬件产生。由此得到的随机数&#xff0c;在产生之前是不可预知的&#xff0c;因此&#xff0c;是真正的随机数。另一种是通过计算机算…

如何产生指定分布的随机数?

参考&#xff1a;https://www.cnblogs.com/xingshansi/p/6539319.html&#xff1b;    https://www.jianshu.com/p/3d30070932a8&#xff1b;    https://blog.csdn.net/pipisorry/article/details/50615652&#xff1b;    https://cosx.org/2015/06/generating-n…

一、三大基础随机分布与数学特征

一、三大基础随机分布 均匀、指数、正态 1、均匀分布 表示在相同长度间隔的分布概率是等可能的 其概率密度、均值、方差 2、指数分布 事件以恒定平均速度连续且独立地发生的过程(泊松过程中的事件之间的时间的概率分布) 其概率密度、均值、方差 3、正态分布 常见的连续概…

AttributeError:Can only use .str accessor with string values!

修改之前&#xff1a; 出现错误&#xff1a;意为matches不是字符串则使用此方法错误 修改方法&#xff1a; 将最后两行代码改为&#xff1a;

“ Can only use .str accessor with string values!”

“ Can only use .str accessor with string values&#xff01;” 出现错误 原代码 解决办法&#xff1a;

vue3报错‘get‘ on proxy: property ‘__accessor__‘ is a read-only and non-configurable data property on t

在使用arcgis地图时候 我把map对象存进了store里面共享数据 结果其他页面使用时候 给我甩了这样一个错误 get on proxy: property __accessor__ is a read-only and non-configurable data property on the proxy target but the proxy did not return its actual value (expe…

Access数据库是什么

数据是当今社会的命脉&#xff0c;因此自然而然地&#xff0c;很多注意力都集中在不同的数据库工具上。毕竟&#xff0c;如果用户有合适的工具&#xff0c;用户就有最有效的方法来处理当前的海量数据过剩问题&#xff0c;或许还能让整个过程变得更易于管理。为此&#xff0c;本…

【ERROR Error: No value accessor for form control with unspecified name attribute】

遇到问题&#xff1a; 控制台报错如下ERROR Error: No value accessor for form control with unspecified name attribute 解决&#xff1a; [(ngModel)]不能直接加在某些标签中 需要同时加ngDefaultControl

access是干什么的软件

Access是一款数据库应用开发工具软件&#xff0c;中文名:微软办公软件-关系数据库管理系统。 access安装包 Access是微软公司于1994年发布的微机数据库管理系统。作为一种功能强大的MIS系统开发工具&#xff0c;它具有界面友好、易学易用、开发简单、界面灵活等特点&#xff0…

Access数据库有什么用?该数据库有什么功能?

对于那些想寻找一个简单的数据库管理系统的用户来说&#xff0c;微软旗下的Access数据库也许是可以让其眼前一亮的工具。 数据库基本定义 Access是Microsoft 365套件工具随附的强大生产力工具&#xff0c;该工具允许用户创建以有组织的结构存储信息的自定义数据库&#xff0c;还…

@Accessors

Accessors 作用&#xff1a;存取器&#xff0c;用于配置getter和setter方法的生成结果 三个属性&#xff1a;fluent、chain、prefix 1、fluent&#xff1a;流畅的&#xff0c;设置为true&#xff0c;getter和setter方法的方法名都是基础属性名&#xff0c;且setter方法返回当前…

使用pandas对数据提取时报错,AttributeError: Can only use .str accessor with string values!

from pandas import DataFrame from pandas import read_excel df read_excel(ri_nuc.xls,sheet_nameSheet4) df.head() 运行结果如下图 df.电话.head().str.strip() 结果出现报错 AttributeError: Can only use .str accessor with string values! 这句话翻译成&#xf…

@Accessors 注解详解

??前言1. Accessors 源码2. Accessors 属性详解2.1 fluent 属性2.2 chain 属性2.3 prefix 属性 前言 在你的工作中&#xff0c;有时候可能会看到Accessors(chain true)这样的注解&#xff0c;他是 lombok 插件包中的一个注解&#xff0c;那么它是什么意思呢&#xff1f; 1.…

lombok里的@Accessors注解

lombok里的Accessors注解 Accessor的中文含义是存取器&#xff0c;Accessors用于配置getter和setter方法的生成结果。 有三个属性 fluent–一个布尔值。如果属实&#xff0c;对于吸气pepper只是pepper()&#xff0c;并且设置器pepper(T newValue)。此外&#xff0c;除非指定…

Linux系统函数之lseek函数

Linux系统函数之lseek函数 fseek与lseek的对比文件存放位置:示例代码:使用lseek函数拓展文件的长度 fseek与lseek的对比 标准C库的函数#include <stdio.h>int fseek(FILE *stream, long offset, int whence);Linux系统函数#include <sys/types.h>#include <uni…

六、Linux文件 - lseek函数

目录 1.lseek函数 2.lseek函数实战 2.1宏SEEK_CUR的用法 2.2宏SEEK_END的用法 3.Open函数实战 - O_APPEND的用法 4.Linux在库函数中寻找相应的宏定义 1.lseek函数 off_t lseek(int fd,off_t offset,int whence);光标的偏移量 fd:文件描述符offset:偏移量whence: SEEK_…