Est-il possible d'utiliser des listes chaînées pour simplifier mon code Monte-Carlo

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

  •  02-10-2019
  •  | 
  •  

Question

Hiya, mon code a actuellement trois fonctions produisant chacune une série massive de nombres aléatoires. Im demandais s'il y a un moyen d'avoir juste une fonction qui retourne une liste chaînée ou tableau multidimensionnel pour le rendre un peu plus propre:

(copié à partir de 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;
}
Était-ce utile?

La solution

Je ne suis pas le premier à signaler que vous ne devez appeler srand une fois, mais je vais vous expliquer pourquoi :

vous appelez le plus souvent srand moins au hasard la sortie est rand.

La fonction rand est un nombre pseudo -Random générateur. Cela signifie qu'il génère des nombres aléatoires qui ont l'air, et ont des propriétés mathématiques correspondant à l'aléatoire, mais ils ne sont pas réellement au hasard. La sortie de rand est en fait une partie fixe, une séquence complètement déterministe de nombres.

Ou plutôt, il produit un d'une grande famille de séquences complètement déterministe. Vous sélectionnez de ces séquences que vous voulez en fournissant une valeur « de semences » à l'aide srand. Lorsque vous donnez un srand x de graines, la prochaine sortie de rand sera le premier numéro de la séquence pseudo-aléatoire (mais complètement déterministe!) Identifié par le x des semences. En d'autres termes:

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

Est-ce que renvoyer des valeurs différentes pour les entrées différentes, mais pour un x donné, retourne toujours le même valeur. Pas du tout! Aléatoire

Ceci est en fait une fonction utile, car si vous découvrez un bug dans un programme qui repose sur la sortie de rand, vous pouvez reproduire de manière fiable le bug en fournissant la même graine à srand afin d'obtenir la même séquence de rand et de sorte que le même comportement de votre programme.

La raison pour laquelle vous avez besoin de srand d'appel est une fois parce que sinon votre programme recevra toujours la même séquence de nombres de rand (la séquence identifiée par graines 1). La raison pour laquelle vous faites pas veulent appeler srand plus d'une fois (dans la plupart des cas) est parce que vous êtes alors obligez à plusieurs reprises arrière rand aux débuts de ses séquences plutôt que de le laisser vous donner l'un d'eux dans sa intégralité. Bien que toute séquence donnée a des propriétés de caractère aléatoire, la séquence de la séquence-débuts ne doit pas nécessairement cette propriété.

De toute évidence, il est en particulier mauvais si vous appelez srand à plusieurs reprises avec même graines, car alors vous refoulant de rand au début du même séquence à chaque fois, et ainsi rand produira toujours le même valeur -. exactement ce que vous ne voulez pas

La raison pour laquelle vous voyez souvent srand(time(NULL)) est parce que le temps est susceptible d'être différent entre deux invocations d'un programme donné, ce qui signifie que chaque fois que le programme exécute utilisera une séquence pseudo-aléatoire différente. Mais time ne retourne que le temps de la granularité des secondes, donc si vous faites cela à plusieurs reprises dans une seule invocation d'un programme, comme dans le vôtre, et moins d'une seconde écoulée entre les appels à srand, vous serez réensemencement à plusieurs reprises avec la même graine, avec des résultats ridicules, comme vous l'avez observé.

Bottom Line: Appel srand exactement une fois, avant la première utilisation de rand. Ayez confiance que les agents d'exécution de la bibliothèque C a écrit un générateur de nombres pseudo-aléatoires décent et ne pas essayer de « augmentation aléatoire » en essayant de compenser les problèmes qui n'existent pas.

Autres conseils

Quelques points:

  1. Ne pas définir RAND_MAX vous.
  2. main retourne un int.
  3. appeler uniquement srand fois.
  4. Supprimez les appels supplémentaires à srand, et utiliser une fonction pour initialiser vos tableaux.
  5. Vous avez défini X, Y et Z sous forme de tableaux, mais vraiment utilisé / nécessaire une valeur chacun.
  6. Il semble y avoir aucune raison d'utiliser l'allocation dynamique puisque vos tableaux de tailles sont fixes.

La seule différence entre vos trois fonctions est de savoir comment ils appellent sleep(). Certes, vous pouvez déplier tout trois en une seule fonction, et l'appeler trois fois dans une boucle?

Seulement srand() appel une fois par appel de programme, généralement à l'intérieur main().

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

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

D'autres personnes ont déjà répondu à certaines questions avec votre programme, mais vous vous rendez compte que vous fuit sur 10 méga-octets de mémoire chaque fois que vous exécutez? free () ...

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top