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

发布于 2024-09-18 19:59:01 字数 2019 浏览 7 评论 0原文

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

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

Hiya, my code currently has three functions each producing a massive array of random numbers. Im wondering if there is a way of just having one function returning a linked list or multidimensional array to make it a bit neater:

(copied from 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;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

起风了 2024-09-25 19:59:01

几点:

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

A few points:

  1. Don't define RAND_MAX yourself.
  2. main returns an int.
  3. Only call srand once.
  4. Eliminate the extra calls to srand, and use one function to initialize your arrays.
  5. You defined X, Y, and Z as arrays, but really only used/needed one value each.
  6. There seems to be no reason to use dynamic allocation since your arrays sizes are fixed.
风吹雨成花 2024-09-25 19:59:01

我不是第一个指出您应该只调用 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 回到开头它的序列而不是让它给你其中一个完整的序列。虽然任何给定的序列都具有随机性的属性,但序列开头的序列不一定具有该属性。

显然,如果您使用相同种子重复调用srand,那会特别糟糕,因为这样您就强制rand每次都回到相同序列的开头,因此rand将始终产生相同值 - 正是您不想要的。

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

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

I'm not the first to point out that you should only call srand once, but I'll explain why:

The more often you call srand the less random the output of rand is.

The rand function is a pseudo-random number generator. That means that it generates numbers that look random, and have mathematical properties corresponding to randomness, but they aren't actually random. The output of rand is actually a fixed, completely deterministic sequence of numbers.

Or, rather, it produces one of a large family of completely deterministic sequences. You select which of these sequences you want by providing a "seed" value using srand. When you give srand a seed x, the next output of rand will be the first number of the pseudo-random (but completely deterministic!) sequence identified by the seed x. In other words:

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

Will return different values for different inputs, but for a given x, will always return the same value. Not at all random!

This is actually a useful feature, since if you discover a bug in a program that relies on the output of rand, you can reliably reproduce the bug by providing the same seed to srand in order to obtain the same sequence from rand and so the same behavior from your program.

The reason that you need to call srand once is because otherwise your program will always receive the same sequence of numbers from rand (the sequence identified by seed 1). The reason you do not want to call srand more than once (in most cases) is because you are then repeatedly forcing rand back to the beginnings of its sequences rather than letting it give you one of them in its entirety. While any given sequence has properties of randomness, the sequence of sequence-beginnings does not necessarily have this property.

Obviously, it's especially bad if you call srand repeatedly with the same seed, because then you're forcing rand back to the beginning of the same sequence every time, and so rand will always produce the same value -- exactly what you don't want.

The reason you commonly see srand(time(NULL)) is because the time is likely to be different between any two invocations of a given program, which means that every time the program runs it will use a different pseudorandom sequence. But time only returns the time to the granularity of seconds, so if you do this repeatedly within a single invocation of a program, as in yours, and less than one second elapses between calls to srand, you will be repeatedly re-seeding with the same seed, with ridiculous results, as you have observed.

Bottom Line: Call srand exactly once, before your first use of rand. Trust that the implementers of the C library wrote a decent pseudo-random number generator, and don't try to "increase randomness" by attempting to compensate for problems that don't exist.

无畏 2024-09-25 19:59:01

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

The only difference between your three functions is how they call sleep(). Surely you can collapse all three into a single function, and call it three times in a loop?

内心荒芜 2024-09-25 19:59:01

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

int main(void) {
    /* initializations */
    srand(time(NULL));

    /* rest of program, with no more calls to srand() */
}

Only call srand() once per program invocation, typically inside main().

int main(void) {
    /* initializations */
    srand(time(NULL));

    /* rest of program, with no more calls to srand() */
}
半城柳色半声笛 2024-09-25 19:59:01

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

Other people already addressed some issues with your program, but do you realize that you are leaking over 10 megabytes of memory every time you run it? free()...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文