2010-09-10 77 views
0

Hiya,我的代码目前有三个函数,每个函数都产生一个大量的随机数。我想知道是否有只是有一个函数返回一个链表或多维数组使它有点整洁的办法:有没有使用链表来简化我的蒙特卡洛代码

(从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

你问了六个问题,从未接受答案。试着去做点什么! – 2010-09-10 20:02:45

+0

为什么你的代码是在pastebin而不是在这里的任何原因? – pmg 2010-09-10 20:08:33

+0

我没有意识到我不得不,我现在去做,欢呼 – JMzance 2010-09-11 18:53:07

回答

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回到它的序列的开始,而不是让它给你一个完整的。虽然任何给定的序列都具有随机性,但序列起始序列并不一定具有此属性。

很显然,如果你调用srand多次与相同的种子,因为那样的话你强迫rand回每次相同序列的开始,所以rand总是会产生它的特别相同值 - 正是你不想要的。

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

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

+1

其实“默认种子”是1. – pmg 2010-09-10 22:16:19

+0

@pmg你是对的。固定。 – 2010-09-10 22:17:34

1

您的三种功能之间的唯一区别是他们如何叫sleep()。当然,你可以将所有三个都合并成一个函数,并在循环中调用它三次?

+0

它生成相同的随机数列表,如果我这样做 – JMzance 2010-09-10 20:25:58

+2

然后不要重置您的随机种子每次。 – 2010-09-10 20:33:31

1

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

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

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

的几点:

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

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

+0

怎么样?我不完全是C能力(但我意识到内存泄漏是坏消息!)所以任何信息将是伟大的 – JMzance 2010-09-11 18:59:11

+0

@Jack:每个'malloc()'('calloc()'在你的情况)**需要** a相应的'free()'或者你有内存泄漏。 'N * 3 * sizeof(double)'> 10Mbytes。你应该在main的结尾处释放(Random_number_list_X)'。 – pmg 2010-09-11 19:10:56