在信号处理领域,获取特定分布的随机信号是一个很常见的需求,这里把均匀分布和高斯分布两种随机信号的生成方法记录一下,权当备忘。
一、首先是均匀分布,一方面均匀分布是最简单的一种情况,其次,均匀分布是后面产生高斯分布的基础。C代码如下:
#include <stdio.h>
#include <
stdlib.h
>
#include <time.h>
void uniform_generator(short *signals, int length, int *max)
{
#include <time.h>
void uniform_generator(short *signals, int length, int *max)
{
int i, max_val;
if(!
signals) {
printf("Empty pointer input\n");
}
srand((unsigned) time(NULL)); //用时间做种子,每次产生随机数不一样
max_val = max ? RAND_MAX : *max; //RAND_MAX定义在stdlib.h, 其值为2147483647
for (i=0; i<length; i++)
{
signals[i]
= rand() % max_val; //产生0-(max_val-1)的随机数
}
}
二、接下来是高斯分布。高斯分布放两个方法,第一种是最基础的基于中心极限定理的方法,第二种是非常巧妙的Box-Muller法。代码如下:
1. 中心极限定理法:
#define NSUM 25
void uniform_generator (double *signals, int length, double avg, double sd)
{
double x = 0;
int i, j;
for(i = 0; i < length; i++)
{
for(j = 0; j < NSUM; j ++) {
x
+= (double)rand() / RAND_MAX;
}
x -= NSUM
/ 2.0;
x /=
sqrt(NSUM / 12.0);
x = avg + (x * sd); //将 x 映射到一个平均值为 m、标准偏差为 sd 的统计量
signals[i] = x;
}
}
2. Box-Muller
法
基本思想: 先得到服从均匀分布的随机数; 然后再将服从均匀分布的随机数转变为服从正态分布。
Box-Muller 是产生随机数的一种方法。Box-Muller 算法隐含的原理非常深奥,但结果却是相当简单。
如果在 (0,1] 值域内有两个一致的随机数字 U1 和 U2,
可以使用以下两个等式中的任一个算出一个正态分布的随机数字 Z:
Z = R * cos( θ ) 或 Z = R * sin( θ )
其中, R = sqrt(-2 * ln(U2)), θ = 2 * π * U1,
正态值 Z 有一个等于 0 的平均值和一个等于 1 的标准偏差,可使用以下等式将 Z 映射到一个平均值为 m、标准偏差为 sd 的统计量 X:
X = m + (Z * sd)。
代码如下:
#define
PI 3.141592654
double
uniform_generator (double *signals, int length, double avg, double sd)
{
static
double U, V;
static
int phase
= 0;
double
z;
int i;
for(i = 0; i < length; i++)
{
if
(phase == 0)
{
U = rand() /
(RAND_MAX + 1
.0);
V = rand() / (RAND_MAX +
1.0);
Z = sqrt(-2.0 *
log(U)) * sin(2.0 * PI *
V);
}
else
{
Z = sqrt(-2.0 * log(U))
* cos(2.0 * PI * V);
}
phase =
1 - phase;
Z = avg + (Z * sd); //将Z 映射到一个平均值为 m、标准偏差为 sd 的统计量
signals[i] = Z;
}
}