C'è un modo di utilizzare liste collegate per semplificare il mio codice di Monte-Carlo

StackOverflow https://stackoverflow.com/questions/3687881

  •  02-10-2019
  •  | 
  •  

Domanda

Hiya, il mio codice attualmente ha tre funzioni ciascuna producendo una massiccia serie di numeri casuali. Im chiedendo se c'è un modo di avere solo una funzione che restituisce una lista collegata o un array multidimensionale per renderlo un po 'più ordinato:

(copiato da 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;
}
È stato utile?

Soluzione

Io non sono il primo a sottolineare che si dovrebbe chiamare solo srand una volta, ma ti spiego perché :

Il più spesso si chiamano srand meno a caso l'output di rand è.

La funzione rand è un pseudo -Random generatore di numeri. Ciò significa che esso genera numeri che guardare casuali, ed hanno proprietà matematiche corrispondenti alla casualità, ma non sono in realtà casuale. L'uscita di rand è in realtà una sequenza completamente deterministica fissa di numeri.

O, piuttosto, produce uno di una grande famiglia di sequenze completamente deterministiche. Si seleziona quale di queste sequenze che si desidera, fornendo un valore di "seme" utilizzando srand. Quando si dà un srand x seme, la prossima uscita del rand sarà il primo numero della sequenza pseudo-casuale (ma completamente deterministico!) Identificato dalla x seme. In altre parole:

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

Sarà restituire valori diversi per gli ingressi diversi, ma per un dato x, restituirà sempre la stesso di valore. Niente affatto! Casuale

Questo è in realtà una funzione utile, dal momento che se si scopre un bug in un programma che si basa sulla produzione di rand, è possibile riprodurre in modo affidabile il bug, fornendo lo stesso seme per srand al fine di ottenere la stessa sequenza da rand e così lo stesso comportamento dal programma.

La ragione per cui è necessario chiamare srand una volta è perché altrimenti il ??programma riceverà sempre la stessa sequenza di numeri da rand (la sequenza identificata da 1 seme). La ragione per cui si fa non desidera chiamare srand più di una volta (nella maggior parte dei casi) è perché si sono poi più volte costringendo indietro rand agli inizi delle sue sequenze piuttosto che lasciare che ti danno uno di loro nella sua interezza. Mentre ogni data sequenza ha proprietà di casualità, la sequenza di sequenza-inizi non deve necessariamente avere questa proprietà.

Ovviamente, è specialmente male se si chiama srand ripetutamente con il stesso di semi, perché allora si sta costringendo indietro rand all'inizio del stesso sequenza ogni volta, e così rand produrrà sempre la stesso valore -. esattamente quello che non vuoi

La ragione per cui comunemente vede srand(time(NULL)) è perché il tempo è probabile che sia diverso tra due invocazioni di un dato programma, il che significa che ogni volta che il programma viene eseguito si userà una diversa sequenza pseudo-casuale. Ma time restituisce solo il tempo per la granularità di secondi, quindi se si esegue questa operazione più volte all'interno di una singola invocazione di un programma, come nel vostro, e meno di un secondo intercorre tra le chiamate a srand, sarete più volte ri-semina con la stesso seme, con risultati ridicoli, come hai osservato.

Bottom Line: Chiamata srand esattamente una volta, prima che il primo uso di rand. La fiducia che gli esecutori della libreria C ha scritto una pseudo-generatore di numeri casuali decente, e non cercare di "aumento casualità", cercando di compensare i problemi che non esistono.

Altri suggerimenti

Alcuni punti:

  1. non definiscono RAND_MAX te stesso.
  2. main restituisce un int.
  3. chiamare Solo srand una volta.
  4. Eliminare le chiamate aggiuntive al srand, e utilizzare una funzione per inizializzare gli array.
  5. È definito X, Y e Z come array, ma in realtà utilizzato solo / necessario un valore ciascuno.
  6. Sembra che ci sia alcun motivo per utilizzare l'allocazione dinamica in quanto gli array dimensioni sono fisse.

L'unica differenza tra le tre funzioni è come lo chiamano sleep(). Sicuramente è possibile comprimere tutti e tre in una sola funzione, e chiamarlo tre volte in un ciclo?

Solo srand() chiamata una volta per programma invocazione, main() tipicamente all'interno.

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

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

Altre persone già affrontati alcuni problemi con il programma, ma non si rendono conto che si sta fuoriuscita di oltre 10 megabyte di memoria ogni volta che lo si esegue? free () ...

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top