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);

或者简单地在循环前随机播种并且不再播种