代码之家  ›  专栏  ›  技术社区  ›  JMzance

有没有办法用链表来简化我的蒙特卡罗代码

  •  0
  • JMzance  · 技术社区  · 14 年前

    嗨,我的代码目前有三个函数,每个函数产生大量的随机数数组。我想知道是否有一种方法可以让一个函数返回一个链表或多维数组,使它更整洁:

    http://pastebin.com/Y5aE6XKS

    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    #ifndef RAND_MAX
    #define RAND_MAX 2147483648
    #endif
    #define N 420000
    
    double* rdm_X(void);
    double* rdm_Y(void);
    double* rdm_Z(void);
    
    void main(void)
    {
       double* Random_number_list_X = rdm_X();
       double* Random_number_list_Y = rdm_Y();
       double* Random_number_list_Z = rdm_Z();
       double X[N+1], Y[N+1], Z[N+1], density = 1, vol = 42.0;
       double sum = 0, sum_x = 0, sum_y = 0, sum_z = 0;
       int i;
    
       for (i = 0; i <= N; i++) {
          X[i] = 3 * Random_number_list_X[i] + 1;
          Y[i] = 7 * Random_number_list_Y[i] - 3;
          Z[i] = 2 * Random_number_list_Z[i] - 1;
          if ((Z[i]*Z[i]) + (sqrt(X[i]*X[i] + Y[i]*Y[i]) - 3)*(sqrt(X[i]*X[i] + Y[i]*Y[i]) - 3) <= 1) {
             sum += density;
             sum_x += X[i] * density;
             sum_y += Y[i] * density;
             sum_z += Z[i] * density;
          }
       }
       printf("(%.5lf, %.5lf, %.5lf)\n",
                sum_x/sum, sum_y/sum, sum_z/sum);
    }
    
    double* rdm_X(void)
    {
       double* Random_number_list_X = calloc(N + 1, sizeof(double));
       int i;
    
       srand(time(NULL));
       for (i = 1; i <= N; i++) {
          Random_number_list_X[i] = (float) rand() / (float) RAND_MAX;
       }
       return Random_number_list_X;
    }
    
    double* rdm_Y(void)
    {
       double* Random_number_list_Y = calloc(N + 1, sizeof(double));
       int i;
       sleep(1);
       srand(time(NULL));
       for (i = 1; i <= N; i++) {
          Random_number_list_Y[i] = (float) rand() / (float) RAND_MAX;
       }
       return Random_number_list_Y;
    }
    
    double* rdm_Z(void)
    {
       double* Random_number_list_Z = calloc(N + 1, sizeof(double));
       int i;
       sleep(2);
       srand(time(NULL));
       for (i = 1; i <= N; i++) {
          Random_number_list_Z[i] = (float) rand() / (float) RAND_MAX;
       }
       return Random_number_list_Z;
    }
    
    5 回复  |  直到 14 年前
        1
  •  4
  •   Tyler McHenry    14 年前

    我不是第一个指出你只应该打电话的人 srand 一次,但我会解释的 :

    斯兰德 这个 较少的 随机输出 rand 是。

    这个 函数是 兰特 实际上是一个固定的,完全确定的数字序列。

    或者,更确切地说,它产生了一个完全确定序列的大家族。您可以通过使用提供“种子”值来选择要使用的序列 斯兰德 斯兰德 一粒种子 x ,的下一个输出 将是伪随机数的第一个数(但完全确定!)由种子识别的序列 . 换句话说:

    int foo(int x)
    {
       srand(x);
       return rand();
    }
    

    对于不同的输入返回不同的值,但是对于给定的 ,将始终返回 价值观。一点也不随意!

    兰特 ,您可以通过向 为了从 你的程序也有同样的行为。

    你需要打电话的原因 斯兰德 兰特 (seed识别的序列 1 想打电话吗 斯兰德 不止一次(在大多数情况下)是因为你反复强迫 回到它的序列的开始,而不是让它给你一个完整的序列。虽然任何给定的序列都具有随机性,但序列开始的序列不一定具有这种特性。

    尤其地 如果你打电话的话就糟了 反复与 相同的 种子,因为那样你就强迫 兰特 相同的 每一次的顺序,等等 将始终产生 相同的 价值——正是你不想要的。

    srand(time(NULL)) 是因为给定程序的任意两次调用之间的时间可能不同,这意味着程序每次运行时都将使用不同的伪随机序列。但是 time 斯兰德

    底线:打电话 斯兰德 就一次,在你第一次使用前 兰特 . 相信C库的实现者编写了一个不错的伪随机数生成器,不要试图通过补偿不存在的问题来“增加随机性”。

        2
  •  6
  •   Jerry Coffin    14 年前

    1. 不定义 RAND_MAX
    2. main 返回一个整数。
    3. 只打电话 srand 一次。
    4. 消除对的额外呼叫 斯兰德 ,并使用一个函数初始化数组。
    5. 您将X、Y和Z定义为数组,但实际上每个数组只使用/需要一个值。
    6. 似乎没有理由使用动态分配,因为数组大小是固定的。
        3
  •  1
  •   Oliver Charlesworth    14 年前

    这三个函数之间的唯一区别是它们如何调用 sleep() . 当然,您可以将这三个函数折叠为一个函数,并在一个循环中调用它三次?

        4
  •  1
  •   pmg    14 年前

    只打电话 srand() 一旦 每次程序调用,通常在 main()

    int main(void) {
        /* initializations */
        srand(time(NULL));
    
        /* rest of program, with no more calls to srand() */
    }
    
        5
  •  1
  •   Jonathan    14 年前

    其他人已经解决了您的程序的一些问题,但是您是否意识到每次运行时都会泄漏超过10兆字节的内存?free()。。。