¿Hay una manera de utilizar las listas enlazadas para simplificar el código de Monte-Carlo

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

  •  02-10-2019
  •  | 
  •  

Pregunta

Hiya, mi código actualmente tiene tres funciones, cada uno produciendo un enorme despliegue de números aleatorios. Im preguntando si hay una manera de tener sólo una función que devuelve una lista enlazada o matriz multidimensional para que sea un poco más ordenado:

(copiado 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;
}
¿Fue útil?

Solución

No soy el primero en señalar que sólo se debe llamar srand una vez, pero voy a explicar ¿Por qué

Cuanto más a menudo se llaman srand el menor al azar la salida de rand es.

La función rand es un seudo generador de números RANDOM. Eso significa que genera números aleatorios que se ven, y que tienen propiedades matemáticas correspondientes a la aleatoriedad, pero no son realmente al azar. La salida del rand es en realidad una secuencia fija, completamente determinista de números.

O, más bien, se produce uno de una gran familia de secuencias completamente determinista. Selecciona cuál de estas secuencias que desee, proporcionando un valor "semilla" usando srand. Cuando le das un srand x semilla, la próxima salida del rand será el primer número de la secuencia pseudo-aleatoria (pero completamente determinista!) Identificado por el x semilla. En otras palabras:

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

Será devolver valores diferentes para diferentes entradas, pero para un x dado, siempre devolverá el mismo valor. No, en absoluto! Aleatoria

Esto es en realidad una función muy útil, ya que si se descubre un error en un programa que se basa en la producción de rand, se puede reproducir de forma fiable el fallo al proporcionar la misma semilla a srand el fin de obtener la misma secuencia de rand y por lo que el mismo comportamiento de su programa.

La razón por la que es necesario srand llamada una vez es porque de lo contrario su programa recibirá siempre la misma secuencia de números del rand (la secuencia identificada por 1 semilla). La razón que hace no desea llamar srand más de una vez (en la mayoría de los casos) es porque se está forzando después repetidamente rand a los inicios de sus secuencias en lugar de dejar que se le dan a uno de ellos en su totalidad. Mientras que cualquier secuencia dada tiene propiedades de aleatoriedad, la secuencia de la secuencia-comienzos no necesariamente tiene esta propiedad.

Obviamente, es de sobre todo mal si se llama srand repetidamente con el mismo semilla, porque entonces estás haciendo retroceder rand al comienzo de la mismo secuencia cada vez, y así rand siempre producirá la em> mismo / em> valor <<-. exactamente lo que usted no quiere

La razón por la que comúnmente se ve srand(time(NULL)) se debe a que probablemente es el momento de ser diferente entre dos invocaciones de un programa dado, lo que significa que cada vez que se ejecuta el programa que utilizará una secuencia pseudoaleatoria diferente. Pero time sólo devuelve el momento de la granularidad de segundos, por lo que si usted hace esto repetidamente dentro de una única invocación de un programa, como en la suya, y menos de un segundo transcurre entre las llamadas a srand, usted será repetidamente re-siembra con el misma semilla, con resultados ridículos, como habrá observado.

Conclusión: Call srand exactamente una vez, antes de su primera utilización de rand. La confianza que los implementadores de la biblioteca C escribió un generador de números pseudo-aleatorios decente, y no tratar de "aumento de aleatoriedad" al tratar de compensar los problemas que no existen.

Otros consejos

A los pocos puntos:

  1. No defina RAND_MAX mismo.
  2. main devuelve un int.
  3. Sólo llame srand vez.
  4. Eliminar las llamadas adicionales a srand, y utilizar una función para inicializar las matrices.
  5. define X, Y, y Z como matrices, pero realmente sólo se utiliza / se necesita un valor de cada uno.
  6. No parece haber ninguna razón para utilizar la asignación dinámica desde sus matrices tamaños son fijos.

La única diferencia entre sus tres funciones es la forma en que ellos llaman sleep(). Sin duda, se puede colapsar los tres en una única función, y lo llaman tres veces en un bucle?

Sólo srand() llamada una vez por la invocación del programa, main() normalmente dentro.

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

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

Otras personas ya se abordan algunos problemas con su programa, pero no se dan cuenta de que se filtra la más de 10 megabytes de memoria cada vez que se ejecuta? libre () ...

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top