2010-09-10 49 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