Gibt es eine Möglichkeit verkettete Listen von mit meinem Monte-Carlo Code zu vereinfachen

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

  •  02-10-2019
  •  | 
  •  

Frage

Hiya, mein Code hat derzeit drei Funktionen jeweils eine massive Reihe von Zufallszahlen zu erzeugen. Ich frage mich, ob es eine Möglichkeit, nur eine Funktion, die eine verknüpfte Liste oder mehrdimensionales Array zurückkehrt, um es ein wenig übersichtlicher zu machen:

(kopiert von 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;
}
War es hilfreich?

Lösung

Ich bin nicht der erste darauf hinweisen, dass Sie nur srand einmal anrufen sollte, aber ich werde erklären, Warum :

Je öfter rufen Sie srand die weniger zufällig die Ausgabe von rand ist.

Die rand Funktion ist ein Pseudo -random Zahlengenerator. Das bedeutet, dass es Zahlen erzeugt, die zufällig aussehen, und haben mathematische Eigenschaften auf Zufälligkeit entsprechen, aber sie sind nicht wirklich zufällig. Der Ausgang des rand ist tatsächlich eine feste, vollständig deterministische Folge von Zahlen.

Oder vielmehr, erzeugt er einen von einer großen Familie von vollständig deterministischen Sequenzen. Sie wählen, welche dieser Sequenzen Sie wollen mit srand einen „Samen“ Wert durch die Bereitstellung. Wenn Sie einen Samen srand geben x, wird die nächste Ausgabe von rand sein die ersten Zahl der Pseudo-Zufall (aber vollständig deterministisch!) Von dem Saatgut x identifizierten Sequenz. Mit anderen Worten:

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

Werden unterschiedliche Werte für verschiedene Eingaben zurück, sondern für eine bestimmte x, wird immer wieder zurückkehren, die gleichen Wert. Nicht bei allen zufällig!

Dies ist eigentlich eine nützliche Funktion, denn wenn Sie einen Fehler in einem Programm zu entdecken, die auf der Ausgabe von rand beruht, können Sie sicher den Fehler reproduzieren, indem die gleichen Samen srand bereitstellt, um die gleiche Sequenz von rand zu erhalten und so das gleiche Verhalten von Ihrem Programm.

Der Grund, dass Sie einmal Anruf srand müssen, weil sonst Ihr Programm immer die gleiche Folge von Zahlen von rand erhalten (die durch Samen 1 identifizierte Sequenz). Der Grund, warum Sie tun, nicht wollen srand mehr anrufen als einmal (in den meisten Fällen) ist, weil Sie werden dann wiederholt rand zurück zu den Anfängen seiner Sequenzen lassen, anstatt sie geben Sie einen von ihnen zwingen in seiner Gesamtheit. Während jede gegebene Sequenzeigenschaften des Zufalls hat, wird die Sequenz von Sequenz-Anfänge nicht unbedingt diese Eigenschaft haben.

Offensichtlich ist es insbesondere schlecht, wenn Sie rufen srand wiederholt mit der gleichen Samen, denn dann bist du rand zurück zum Anfang des same zwingen jede Zeitfolge, und so rand den gleichen Wert immer produzieren -. genau das, was Sie nicht wollen,

Der Grund, warum Sie häufig srand(time(NULL)) sehen ist, weil die Zeit wahrscheinlich zwischen zwei beliebigen Anrufungen eines bestimmten Programms, anders zu sein, was bedeutet, dass jedes Mal das Programm läuft es eine andere Pseudo-Zufallsfolge verwenden. Aber time nur die Zeit, um die Granularität von Sekunden zurückkehrt, so dass, wenn Sie dies tun, wiederholt in einem einzigen Aufruf eines Programms, wie es in dir, und weniger als eine Sekunde verstreicht zwischen den Anrufen zu srand, werden Sie immer wieder neu Impfen mit der gleiche Samen, mit lächerlichen Ergebnissen, wie Sie beobachtet haben.

Fazit: Anruf srand genau einmal, vor dem ersten Gebrauch von rand. Vertrauen, dass die Implementierer der C-Bibliothek einen anständigen Pseudo-Zufallszahlengenerator geschrieben, und versuchen Sie nicht, auf „Erhöhung Zufälligkeit“ von für Probleme zu kompensieren versuchen, die sich nicht gibt.

Andere Tipps

Einige Punkte:

  1. definiert nicht RAND_MAX selbst.
  2. main gibt ein int.
  3. rufen Nur srand einmal.
  4. Beseitigen Sie die zusätzlichen Anrufe srand, und eine Funktion verwenden, um Ihre Arrays zu initialisieren.
  5. Sie definierten X, Y und Z wie Arrays, aber wirklich nur dann verwendet / benötigten je einen Wert.
  6. Es scheint keinen Grund zu sein, die dynamische Zuordnung zu verwenden, da Ihre Arrays Größen festgelegt sind.

Der einzige Unterschied zwischen den drei Funktionen ist, wie sie nennen sleep(). Sicherlich können Sie alle drei in einer einzigen Funktion zusammenfallen, und es dreimal in einer Schleife nennen?

Nur Anruf srand() einmal pro Programmaufruf, in der Regel innerhalb main().

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

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

Andere Personen adressierte bereits einige Probleme mit Ihrem Programm, aber Sie feststellen, dass Sie über 10 Megabyte Speicher undicht sind jedes Mal, wenn es laufen? (Kostenlos) ...

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top