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;
}
4

5 回答 5

6

几点:

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

我不是第一个指出你应该只打电话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其序列的开头,而不是让它完整地给您其中一个。虽然任何给定的序列都具有随机性,但序列开始的序列不一定具有这种性质。

显然,如果你用同一个种子重复调用,那就特别糟糕,因为你每次都强制回到同一个序列的开头,所以总是会产生相同的值——这正是你不想要的。srandrandrand

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

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

于 2010-09-10T22:09:21.517 回答
1

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

于 2010-09-10T20:20:00.867 回答
1

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

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

    /* rest of program, with no more calls to srand() */
}
于 2010-09-10T20:33:52.393 回答
1

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

于 2010-09-10T21:47:23.510 回答