2012-04-28 16 views
23

No estoy seguro de qué otra manera de explicar esto, por lo que el título describe bastante bien el problema.¿Por qué System.Random da '1' muchas veces seguidas, luego no por un tiempo, luego otra vez?

Al azar no se reinicializa cada parte del ciclo. Es un miembro estático de una clase a la que siempre llamo desde otras clases.

No estoy utilizando una semilla personalizada.

El código de inicialización es:

public static Random random = new Random(); 

     for (int x = 0; x < 75; x++) 
     { 
      if (main.random.Next(11) == 1) 
      { 
       tiles[heightMap[x] - 1][x] = 4; 
       tiles[heightMap[x] - 2][x] = 4; 
       tiles[heightMap[x] - 3][x] = 4; 
       tiles[heightMap[x] - 4][x] = 4; 
       tiles[heightMap[x] - 5][x] = 4; 
       tiles[heightMap[x] - 5][x - 1] = 5; 
       tiles[heightMap[x] - 6][x - 1] = 5; 
       tiles[heightMap[x] - 6][x] = 5; 
       tiles[heightMap[x] - 5][x + 1] = 5; 
       tiles[heightMap[x] - 6][x + 1] = 5; 
      } 
     } 

Este (Soy consciente de que esto no es una gran manera - es rudimentario y temporal) genera un árbol.

Sin embargo, mi terreno a menudo se ve algo como esto, con muchos árboles agrupados:

☁☁☁☁☁☁☁☁☁☁

¿Alguien puede dar una idea de por qué ocurre esto? ¿Hay una mejor alternativa que usar la clase System.Security.Cryptography.Random?

Esperaría un promedio de 9 huecos por árbol, pero es más como 7 y luego 3 árboles muy agrupados.

enter image description here

+15

http://dilbert.com/strips/comic/2001-10 -25/ –

+0

Bonito comic, muy cierto. :( –

+3

Aleatorio no significa cambios frecuentes en los resultados alternativos. Con el tiempo, la secuencia de este tipo se distribuye de manera uniforme. – codekaizen

Respuesta

35

esto es un malentendido probabilidad; todo lo que sabe es que en cualquier punto, la posibilidad de adquirir un árbol en la siguiente ranura decir, suponiendo una distribución uniforme, 1 en 11.

La probabilidad de contraer una brecha de 0 es, pues, 1/11

La probabilidad de contraer una brecha de 1 es por lo tanto 10/11 * 1/11

La probabilidad de tener un espacio de 2 es, pues, 10/11 * 10/11 * 1/11

etc

Todos esos 10/11 agregar (bueno, multiplicar) arriba! Así que vamos a escribir una utilidad:

decimal accountedFor = 0M; 
for (int i = 0; i <= 20; i++) 
{ 
    decimal chance = 1M/11M; 
    for (int j = 0; j < i; j++) chance *= 10M/11M; 
    accountedFor += chance; 
    Console.WriteLine("{0:00}: {1:00.0%}\t({2:00.0%})", i, chance, accountedFor); 
} 

Lo que da:

00: 09.1%  (09.1%) 
01: 08.3%  (17.4%) 
02: 07.5%  (24.9%) 
03: 06.8%  (31.7%) 
04: 06.2%  (37.9%) 
05: 05.6%  (43.6%) 
06: 05.1%  (48.7%) 
07: 04.7%  (53.3%) 
08: 04.2%  (57.6%) 
09: 03.9%  (61.4%) 
10: 03.5%  (65.0%) 
11: 03.2%  (68.1%) 
12: 02.9%  (71.0%) 
13: 02.6%  (73.7%) 
14: 02.4%  (76.1%) 
15: 02.2%  (78.2%) 
16: 02.0%  (80.2%) 
17: 01.8%  (82.0%) 
18: 01.6%  (83.6%) 
19: 01.5%  (85.1%) 
20: 01.4%  (86.5%) 

lo que explica el sesgo para las pequeñas lagunas. Nota; cuando alcanzamos una brecha de tamaño 20, estamos en un territorio con probabilidad inferior al 1,5% y hemos representado el 85% de todos los resultados posibles; el 15% restante se repartirá entre el resto del infinito (es decir, un espacio vacío). del tamaño 13212 es posible, pero muy improbable).

Así que aquí es una simulación:

int[] gapCounts = new int[21]; 

int gap = 0; 
// simulate a few gaps using your algo 
var random = new Random(); 
for (int x = 0; x < 100000; x++) 
{ 
    if (random.Next(11) == 1) 
    { // count that gap 
     gapCounts[gap]++; 
     gap = 0; 
    } 
    else 
    { 
     gap++; 
     if(gap >= gapCounts.Length) 
     { // just skip anything too large, sorry 
      gap = 0; 
     } 
    } 
} 

decimal total = gapCounts.Sum(); 
for(int i = 0 ; i < gapCounts.Length ; i++) 
{ 
    Console.WriteLine("{0:00}: {1:00.0%}", i, gapCounts[i]/total); 
} 

con la salida nada que estos valores cambiarán cada carrera:

00: 11.0% 
01: 09.4% 
02: 08.6% 
03: 07.9% 
04: 07.3% 
05: 06.5% 
06: 05.4% 
07: 05.4% 
08: 04.7% 
09: 04.5% 
10: 04.4% 
11: 03.4% 
12: 03.5% 
13: 03.0% 
14: 02.9% 
15: 02.4% 
16: 02.5% 
17: 02.2% 
18: 01.9% 
19: 01.5% 
20: 01.7% 
+0

Muy buena respuesta, felicitaciones. – yamen

+0

Sí, muestra la versión acumulativa en ejecución de lo anterior, será esclarecedor. – yamen

+0

Pero parece inclinarse mucho hacia 1 y 7, mientras que números como 2 son muy raramente escogidos (en una cadena de 75 números, 2 fueron seleccionados solo cuatro veces, y estoy obteniendo mucho este tipo de resultado). También parece muy común obtener tres 7 seguidos, y luego no 7s durante mucho tiempo. Esto no es solo en una carrera, estoy obteniendo muchos patrones similares a ese triple 7 y raros 2 casos. Desde un punto de vista matemático, puedo ver de dónde vienes, pero creo que es la clase .NET de System.Random que no tiene un algoritmo lo suficientemente bueno. –

Cuestiones relacionadas