C:尝试制作一个 m*n 随机正态分布数字矩阵(极坐标形式的 Box muller 2)
C: Trying to make a matrix of m*n random normal distributed numbers (Box muller 2 on polar form)
我正在尝试用正态分布的随机数填充一个 m x n
数组,其中正态分布的数字定义如代码所示,您首先必须找到两个均匀分布的数字和 r , 定义 2 个正态分布的数。当我 运行 程序时,它只是在数组中一遍又一遍地打印相同的两个数字,就好像代码中的变量 rv_new
只是保持相同的结构一样。
以下是应该生成和打印数字的代码部分。我猜这个错误可能与 rejection_sampling()
函数有关(将其作为结构是不是很愚蠢?)。
typedef struct rv rv;
struct rv {
double v1;
double v2;
double r;
};
/*Function prototypes*/
double **malloc_array2d(size_t m, size_t n);
rv rejection_sampling(void);
void free_array2d(double ** B);
int main(void) {
unsigned int m, n;
double **A;
... (user input to get m and n)
/*Dynamically allocate a m-by-n array of doubles*/
A = malloc_array2d(m,n);
if (A == NULL) {
free_array2d(A);
printf("Memory allocation failed\n");
return EXIT_FAILURE;
}
//it is here I try to make the matrix:
for (int i = 0; i <= m * n - 1; i++) {
if (i % 2 == 0) {
rv rv_new = rejection_sampling();
A[0][i] = rv_new.v1 * (sqrt(-2 * log(pow(rv_new.r, 2)))) / rv_new.r;
A[0][i+1] = rv_new.v2 * (sqrt(-2 * log(pow(rv_new.r, 2)))) / rv_new.r;
}
else {;}
}
/*printing of the 2D-array with the m*n normally uniformly distributed numbers*/
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
printf(" %5.2f", A[i][j]);
}
printf("\n");
}
}
/*Free memory and return*/
free_array2d(A);
return 0;
}
rv rejection_sampling(void) { // Function that returns a struct containing a sample (v1,v2) and r
double v1 = 0;
double v2 = 0;
double r = 0;
double Randmax = RAND_MAX;
srand(time(NULL)); //Seed to the rand-function
do {
v1 = rand() / Randmax; //uniformly distributed random numbers between [0,1]
v2 = rand() / Randmax;
v1 = -1 + 2 * v1; //uniformly distributed random numbers between [-1,1]
v2 = -1 + 2 * v2;
r = sqrt(pow(v1, 2) + pow(v2, 2));
} while (r >= 1 || r == 0);
rv new_rv; //creates struct
new_rv.v1 = v1;
new_rv.v2 = v2;
new_rv.r = r;
return new_rv;
}
void free_array2d(double ** A){
if ( A == NULL) return;
free(A[0]);
free(A);
return;
}
double ** malloc_array2d(size_t m, size_t n){
double **A;
size_t i;
A = (double **) malloc(m*sizeof(double *));
if (A == NULL)
return NULL;
A[0]=(double *)malloc(m*n*sizeof(double));
if ( A[0] == NULL) {
free(A);
return NULL;}
for(i = 1; i < m; i++)
A[i]=A[0]+i*n;
return A;
}
您的问题是您在 rejection_sampling
函数中生成随机数时,每次 调用 srand(time(NULL));
。
您需要将 srand(time(NULL));
移动到 main
函数的开头:)
说明
假设您有一个包含 "random" 个数字的列表,每次调用 rand()
它都会为您提供列表中的值,然后移动到下一个值。问题是每次你 运行 你的程序,你都会得到相同的 "random" 数字序列。解决方案是在该列表中选择一个 "random" 起始位置 - 即 "seeding" - 通常使用当前时间完成。你无意中做的是每次你想要一个随机数时重置到这个 "random" 列表中的相同位置,所以你会得到相同的值(至少每秒)。
也许进展太快了,srand(time(NULL));
总是给你相同的种子。尝试像这样
向 rejection_sampling
提供反馈
rv rejection_sampling(int feedback){ //This feedback could be the i in your loop
// ...
srand(time(NULL)+feedback);
或者简单地在循环前随机播种并且不再播种
我正在尝试用正态分布的随机数填充一个 m x n
数组,其中正态分布的数字定义如代码所示,您首先必须找到两个均匀分布的数字和 r , 定义 2 个正态分布的数。当我 运行 程序时,它只是在数组中一遍又一遍地打印相同的两个数字,就好像代码中的变量 rv_new
只是保持相同的结构一样。
以下是应该生成和打印数字的代码部分。我猜这个错误可能与 rejection_sampling()
函数有关(将其作为结构是不是很愚蠢?)。
typedef struct rv rv;
struct rv {
double v1;
double v2;
double r;
};
/*Function prototypes*/
double **malloc_array2d(size_t m, size_t n);
rv rejection_sampling(void);
void free_array2d(double ** B);
int main(void) {
unsigned int m, n;
double **A;
... (user input to get m and n)
/*Dynamically allocate a m-by-n array of doubles*/
A = malloc_array2d(m,n);
if (A == NULL) {
free_array2d(A);
printf("Memory allocation failed\n");
return EXIT_FAILURE;
}
//it is here I try to make the matrix:
for (int i = 0; i <= m * n - 1; i++) {
if (i % 2 == 0) {
rv rv_new = rejection_sampling();
A[0][i] = rv_new.v1 * (sqrt(-2 * log(pow(rv_new.r, 2)))) / rv_new.r;
A[0][i+1] = rv_new.v2 * (sqrt(-2 * log(pow(rv_new.r, 2)))) / rv_new.r;
}
else {;}
}
/*printing of the 2D-array with the m*n normally uniformly distributed numbers*/
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
printf(" %5.2f", A[i][j]);
}
printf("\n");
}
}
/*Free memory and return*/
free_array2d(A);
return 0;
}
rv rejection_sampling(void) { // Function that returns a struct containing a sample (v1,v2) and r
double v1 = 0;
double v2 = 0;
double r = 0;
double Randmax = RAND_MAX;
srand(time(NULL)); //Seed to the rand-function
do {
v1 = rand() / Randmax; //uniformly distributed random numbers between [0,1]
v2 = rand() / Randmax;
v1 = -1 + 2 * v1; //uniformly distributed random numbers between [-1,1]
v2 = -1 + 2 * v2;
r = sqrt(pow(v1, 2) + pow(v2, 2));
} while (r >= 1 || r == 0);
rv new_rv; //creates struct
new_rv.v1 = v1;
new_rv.v2 = v2;
new_rv.r = r;
return new_rv;
}
void free_array2d(double ** A){
if ( A == NULL) return;
free(A[0]);
free(A);
return;
}
double ** malloc_array2d(size_t m, size_t n){
double **A;
size_t i;
A = (double **) malloc(m*sizeof(double *));
if (A == NULL)
return NULL;
A[0]=(double *)malloc(m*n*sizeof(double));
if ( A[0] == NULL) {
free(A);
return NULL;}
for(i = 1; i < m; i++)
A[i]=A[0]+i*n;
return A;
}
您的问题是您在 rejection_sampling
函数中生成随机数时,每次 调用 srand(time(NULL));
。
您需要将 srand(time(NULL));
移动到 main
函数的开头:)
说明
假设您有一个包含 "random" 个数字的列表,每次调用 rand()
它都会为您提供列表中的值,然后移动到下一个值。问题是每次你 运行 你的程序,你都会得到相同的 "random" 数字序列。解决方案是在该列表中选择一个 "random" 起始位置 - 即 "seeding" - 通常使用当前时间完成。你无意中做的是每次你想要一个随机数时重置到这个 "random" 列表中的相同位置,所以你会得到相同的值(至少每秒)。
也许进展太快了,srand(time(NULL));
总是给你相同的种子。尝试像这样
rejection_sampling
提供反馈
rv rejection_sampling(int feedback){ //This feedback could be the i in your loop
// ...
srand(time(NULL)+feedback);
或者简单地在循环前随机播种并且不再播种