【问题标题】:Is there a way of using linked lists to simplify my Monte-Carlo code有没有办法使用链表来简化我的蒙特卡洛代码
【发布时间】:2010-09-10 19:55:37
【问题描述】:

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

(复制自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;
}

【问题讨论】:

  • 您问了六个问题,但从未接受过答案。尝试对此做点什么!
  • 您的代码在 pastebin 中而不是在此处的任何原因?
  • 我没有意识到我必须这样做,我现在就去做,干杯

标签: c linked-list montecarlo


【解决方案1】:

几点:

  1. 不要自己定义RAND_MAX
  2. main 返回一个整数。
  3. 只调用一次srand
  4. 消除对srand 的额外调用,并使用一个函数来初始化您的数组。
  5. 您将 X、Y 和 Z 定义为数组,但实际上每个只使用/需要一个值。
  6. 似乎没有理由使用动态分配,因为您的数组大小是固定的。

【讨论】:

    【解决方案2】:

    我不是第一个指出您应该只调用一次srand,但我会解释为什么

    您调用srand 的次数越多,rand 的输出就越随机

    rand 函数是一个-随机数生成器。这意味着它生成的数字看起来是随机的,并且具有与随机性相对应的数学属性,但它们实际上并不是随机的。 rand 的输出实际上是一个固定的、完全确定的数字序列。

    或者,更确切地说,它产生了一大类完全确定性序列中的一个。您可以通过使用srand 提供“种子”值来选择您想要的这些序列中的哪一个。当你给srand 一个种子x 时,rand 的下一个输出将是由种子x 标识的伪随机(但完全确定!)序列的第一个数字。换句话说:

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

    将为不同的输入返回不同的值,但对于给定的x,将始终返回相同的值。一点都不随机!

    这实际上是一个有用的功能,因为如果您在依赖于rand 输出的程序中发现了一个错误,您可以通过向srand 提供相同的种子来可靠地重现该错误以获得相同的来自rand 的序列,因此您的程序中的行为相同。

    您需要调用srand 一次的原因是,否则您的程序将始终从rand 接收相同的数字序列(由种子1 标识的序列)。你之所以想要多次调用srand(在大多数情况下)是因为你会反复迫使rand回到其序列的开头,而不是让它给你一个他们的全部。虽然任何给定的序列都具有随机性,但序列开始的序列不一定具有这种性质。

    显然,如果您使用 same 种子反复调用 srand,这尤其 很糟糕,因为那样你会强制 rand 回到 的开头em>same 序列每次,所以rand 总是会产生 same 值——这正是你不想要的。

    您经常看到srand(time(NULL)) 的原因是因为给定程序的任何两次调用之间的时间可能不同,这意味着每次程序运行时都会使用不同的伪随机序列。但是time 只将时间返回到秒的粒度,所以如果你在一个程序的单个调用中重复执行此操作,就像你的那样,并且在调用srand 之间间隔不到一秒,你将被重复- 用相同的种子播种,结果荒谬,正如你所观察到的。

    底线:在您第一次使用rand 之前,只调用一次srand。相信 C 库的实现者编写了一个不错的伪随机数生成器,不要试图通过补偿不存在的问题来“增加随机性”。

    【讨论】:

    • 其实“默认种子”是1。
    【解决方案3】:

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

    【讨论】:

    • 如果我这样做,它会生成相同的随机数列表
    • 那么不要每次都重置你的随机种子。
    【解决方案4】:

    每次程序调用只调用srand()一次,通常在main()内。

    int main(void) {
        /* initializations */
        srand(time(NULL));
    
        /* rest of program, with no more calls to srand() */
    }
    

    【讨论】:

      【解决方案5】:

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

      【讨论】:

      • 怎么样?我还不能完全胜任 C(但我意识到内存泄漏是个坏消息!)所以任何信息都会很棒
      • @Jack:每个malloc()(在您的情况下为calloc()需要相应的free(),否则您有内存泄漏。 N * 3 * sizeof (double) > 10Mbytes。你应该在 main 的末尾free(Random_number_list_X)
      猜你喜欢
      • 2015-01-26
      • 1970-01-01
      • 1970-01-01
      • 2022-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-04
      相关资源
      最近更新 更多