前言
程序中常见的随机数函数通常都是均匀分布的,有时我们需要按照一个非均匀的概率来生成数字。
对于离散随机而言,可以通过分区实现,本文只讨论连续型随机变量的逆变换法。
这里所说的均匀与非均匀实际上指的是概率密度函数:
概率密度函数
在连续型随机变量中,概率密度函数是一个描述这个随机变量的输出值在某个确定的取值点附近的可能性的函数。
累积概率分布
设是一个随机变量,
是任意实数,函数
称为的累积概率分布函数,该函数具有以下性质:
1.有界性
2.单调性
3.右连续性
根据概率密度函数生成随机数
已有均匀分布的随机数,需要获得一个按指定概率密度分布的随机数;
根据累积概率分布函数的性质,我们已有的其实是在0-1区间(对应有界区间)上服从均匀分布的随机数
,我们想得到的是x的分布,所以我们需要的便是将均匀分布随机数的值带入累计概率密度的反函数(对于连续型随机变量,F(x)在区间(0,1)的反函数一定存在),
就是我们需要的。
简单点说,就是将F(x)在dy微元映射到x轴的dx微元,是一个将均匀分布映射回x分布的过程。
例子:在圆形内按面积随机
现在我们随机生成一些点,这些点在半径为的圆形中均匀分布。
我们先用均匀分布的半径与均匀分布的角度生成一遍:
public void RandomRadioAndAngel()
{
for (int i = 0; i < 5000; i++)
{
float radio = Random.Range(0f, R);
float angel = Random.Range(0f, 360f);
Vector2 offset = Quaternion.Euler(0, 0, angel) * Vector2.right * radio;
//生成点的方法
InstanceCell(offset);
}
}
生成结束后(图-1 左),可以发现越靠近圆心的地方密度越大,这是因为我们需要的沿半径的概率分布并非均匀分布。
圆形的半径处,
所对应的面积是
,并不是均匀分布,这里的概率密度函数是
累积概率分布函数为概率密度函数的积分:
累积概率分布函数的反函数(注意这里是开区间):
接下来按照这个函数重新随机:
public void RandomCircleArea()
{
for (int i = 0; i < 5000; i++)
{
float radio = R * Mathf.Pow(Random.Range(0f, 1f), 0.5f);
float angel = Random.Range(0f, 360f);
Vector2 offset = Quaternion.Euler(0, 0, angel) * Vector2.right * radio;
//生成点的方法
InstanceCell(offset);
}
}