C:尝试制作一个m * n随机正态分布数的矩阵(极坐标形式的Box muller 2)

时间:2015-10-21 13:41:48

标签: c random-sample

我试图用正态分布的随机数填充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;
}

2 个答案:

答案 0 :(得分:4)

您的问题是,您在srand(time(NULL));功能中生成随机数的每个时间都会调用rejection_sampling

您需要将srand(time(NULL));移至main功能的开头:)

<强>解释

想象一下,你有一个&#34;随机&#34;的列表数字,每次调用rand()时,它会为您提供列表中的值,然后移动到下一个值。问题是,每次运行程序时,都会得到相同的序列&#34;随机&#34;数字。解决方案是选择&#34;随机&#34;在该列表中的起始位置 - 这是&#34;播种&#34; - 通常使用当前时间完成。你无意中做了什么,重置到这个&#34;随机&#34;中的相同位置。每次你想要一个随机数字列表,所以你会得到相同的值(至少每秒)。

答案 1 :(得分:0)

也许它太快了srand(time(NULL));给你总是相同的种子。尝试向这样的rejection_sampling提供反馈

rv rejection_sampling(int feedback){ //This feedback could be the i in your loop
    // ...
    srand(time(NULL)+feedback);

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