2009-02-03 24 views

Respuesta

6

Supongo que usted mea n números pseudoaleatorios. El más simple que conozco (al escribir juegos de videojuegos en máquinas antiguas) funcionaba así:

seed = seed * 5 + 1;

Lo haces cada vez que se invoca al azar y luego utilizas la cantidad de bits bajos que quieras. * 5 + 1 tiene la propiedad agradable (IIRC) de aprovechar todas las posibilidades antes de repetir, sin importar cuántos bits estés mirando.

La desventaja, por supuesto, es su previsibilidad. Pero eso no importó en los juegos. Estábamos agarrando números aleatorios como locos para todo tipo de cosas, y nunca sabrías qué número vendría después.

Haz un par de cosas como esta en paralelo y combina los resultados. Este es un generador congruente lineal.

+0

¡Esas son elecciones horribles de a, c y m! – derobert

+1

Haha. Sí, pero la primera vez que vi esa rutina fue en una máquina de 1 MHz. :-) – Nosredna

8

POSIX.1-2001 muestra el siguiente ejemplo de una implementación de rand() y srand(), posiblemente útil cuando se necesita la misma secuencia en dos máquinas diferentes.

static unsigned long next = 1; 
/* RAND_MAX assumed to be 32767 */ 
int myrand(void) { 
    next = next * 1103515245 + 12345; 
    return((unsigned)(next/65536) % 32768); 
} 
void mysrand(unsigned seed) { 
    next = seed; 
} 
5

Aloha!

¿De manera manual quiere decir "no usar la computadora" o "escribir mi propio código"?

SI no está utilizando la computadora puede usar cosas como dados, números en una bolsa y todos los métodos vistos en la tele cuando seleccionan equipos, ganan series de Bingo, etc. Las Vegas está llena de este tipo de métodos utilizados en los procesos (juegos) destinados a darle malas probabilidades y retorno de la inversión. También puede obtener el gran libro RAND y vuelta a una página seleccionada al azar:

http://www.amazon.com/Million-Random-Digits-Normal-Deviates/dp/0833030477

(También, por alguna de atracciones, leer los comentarios)

Para escribir su propio código debe tener en cuenta qué no usar el sistema proporcionado RNG no es lo suficientemente bueno. Si está utilizando un sistema operativo moderno, tendrá un RNG disponible para programas de usuario que deberían ser lo suficientemente buenos para su aplicación.

Si realmente necesita implementar uno propio, hay un gran grupo de generadores disponibles.Para un uso que no sea de seguridad, puede ver las cadenas LFSR, los generadores congruenciales, etc. Cualquiera que sea la distribución que necesite (uniforme, normal, exponencial, etc.) debería ser capaz de encontrar descripciones de algoritmos y bibliotecas con implementaciones.

Para el uso de seguridad, debe observar cosas como Yarrow/Fortuna, el NIST SP 800-89, PRNG especificados y RFC 4086 para obtener buenas fuentes de entropía necesarias para alimentar el PRNG. O incluso mejor, utilice el que está en el sistema operativo que debe cumplir con los requisitos de seguridad RNG.

La implementación de RNG puede ser un ejercicio divertido, pero rara vez se necesita. Y no invente su propio algoritmo a menos que sea para aplicaciones de juguetes. NO, repita NO invente RNG para aplicaciones de seguridad (generando claves criptográficas, por ejemplo), al menos a menos que realice una lectura e investigación seria. Me lo agradecerás (espero).

+0

N nit: "También puede obtener el gran libro RAND y pasar a una página seleccionada al azar". Eso sería muy sesgado hacia los números que estén en el medio del libro en la parte superior de la página. Las personas son RNG terribles. – Malvolio

+0

Pasar a una página específica de un libro de números aleatorios verdaderos no sesga el resultado, siempre y cuando no reutilice los números, porque los números en el medio del libro son tan aleatorios como los del frente. Reutilizar números sesgará el resultado, sin importar de qué página los seleccione. –

3

Espero que no sea redundante porque no he leído todos los enlaces, pero creo que puede obtener bastante cerca de verdadero generador aleatorio. hoy en día los sistemas son a menudo tan complejos que hasta los mejores geeks necesitan mucho tiempo para entender que está pasando dentro de :)

solo abre tu mente y piensa si puedes monitorear alguna propiedad del sistema global, úsala para sembrar ... Elija un paquete de red (¿no es para usted?) y calcule "algo" fuera de su contenido y úselo para sembrar en ... etc.

puede diseñar el mejor para sus necesidades con todas esas pistas alrededor;)

5
static void Main() 
    { 
     DateTime currentTime = DateTime.Now; 

     int maxValue = 100; 

     int hour = currentTime.Hour; 
     int minute = currentTime.Minute; 
     int second = currentTime.Second; 
     int milisecond = currentTime.Millisecond; 

     int randNum = (((hour + 1) * (minute + 1) * (second + 1) * milisecond) % maxValue); 

     Console.WriteLine(randNum); 

     Console.ReadLine(); 
    } 

Above muestra una pieza de código muy simple para generar números aleatorios. Es un programa de consola escrito en C#. Si conoce algún tipo de programación básica, debería ser comprensible y fácil de convertir a cualquier otro idioma deseado.

DateTime simplemente toma una fecha y hora actual, la mayoría de los lenguajes de programación tienen una función para hacer esto.

Las variables de hora, minuto, segundo y milisegundo rompen la fecha y hora, lo valoran en sus partes componentes. Solo estamos interesados ​​en estas partes, así que podemos ignorar el día. De nuevo, en la mayoría de los idiomas, las fechas y horas se presentan generalmente como cadenas. En .Net tenemos instalaciones que nos permiten analizar esta información fácilmente. Pero en la mayoría de los otros idiomas donde los tiempos se presentan como cadenas, no es excesivamente difícil analizar la cadena de las partes que desea y convertirlas a sus números. Estas instalaciones generalmente se proporcionan incluso en el idioma más antiguo.

La semilla esencialmente nos da un número inicial que siempre cambia. Tradicionalmente, usted simplemente multiplicaría este número por un valor decimal entre 0 y 1, esto corta ese paso.

upperRange define el valor máximo. Entonces el número generado nunca estará por encima de este valor. Además, nunca estará debajo de 0. Así que no hay ingredientes. Pero si quieres negativos, puedes negarlo manualmente. (Multiplicándolo por -1)

La variable real randNumis lo que depara el valor aleatorio le interesa.

El truco es conseguir que el resto (módulo) después de dividir la semilla por el rango superior. El resto siempre será más pequeño que el divisor, que en este caso es 100. Las matemáticas simples le dicen que no puede tener un resto mayor que el divisor. Entonces, si divide por 10, no puede tener un resto mayor que 10. Es esta ley simple la que nos da nuestro número aleatorio entre 0 y 100 en este caso.

console.writeline simplemente lo envía a la pantalla.

console.readline simplemente pausa el programa para que pueda verlo.

Esta es una pieza de código muy simple para generar números aleatorios. Si ejecutó este programa en el mismo interblo exactamente todos los días (pero tendría que hacerlo a la misma hora, minuto, segundo y milisegundo) durante más de 1 día, comenzaría a generar el mismo conjunto de números una y otra vez día adicional. Esto es porque está ligado al tiempo. Esa es la resolución del generador. Entonces, si conoce el código de este programa y la hora en que se ejecuta, puede predecir el número generado, pero no será fácil. Es por eso que usé milisegundos. Usa segundos o minutos solo para ver a qué me refiero. Entonces, podría escribir una tabla que muestre cuándo 1 entra, 0 sale, cuándo 2 entra 0, etc. Luego, puede predecir la salida para cada segundo y el rango de números generados. Cuanto más aumente la resolución (al aumentar los números que cambian), más difícil será y más tiempo se tardará en obtener un patrón predecible. Este método es lo suficientemente bueno para el uso de la mayoría de las personas.

Esa es la manera de la vieja escuela de generar números al azar para juegos básicos. Necesita ser rápido y simple. Es. Esto también resalta exactamente por qué, los genaerators de números aleatorios no son realmente aleatorios sino psudo aleatorios.

Espero que esta sea una respuesta razonable a su pregunta.

3

El Mersenne twister tiene un período muy largo (2^19937-1).

Aquí hay una aplicación muy básica en C++:

struct MT{ 
    unsigned int *mt, k, g; 
    ~MT(){ delete mt; } 
    MT(unsigned int seed) : mt(new unsigned int[624]), k(0), g(0){ 
     for (int i=0; i<624; i++) 
      mt[i]=!i?seed:(1812433253U*(mt[i-1]^(mt[i-1]>>30))+i); 
    } 
    unsigned int operator()(){ 
     unsigned int q=(mt[k]&0x80000000U)|(mt[(k+1)%624]&0x7fffffffU); 
     mt[k]=mt[(k+397)%624]^(q>>1)^((q&1)?0x9908b0dfU:0); 
     unsigned int y = mt[k]; 
     y ^= (y >> 11); 
     y ^= (y << 7) & 0x9d2c5680U; 
     y ^= (y << 15) & 0xefc60000U; 
     y ^= (y >> 18); 
     k = (k+1)%624; 
     return y; 
    } 
}; 
3

Una buena manera de obtener números aleatorios es monitorear el nivel ambiental de ruido que entra por el micrófono del ordenador. Si puede obtener un controlador (o un idioma que admita entrada de micrófono) y convertirlo en un número, ¡ya está en camino!

También se ha investigado cómo obtener "verdadera aleatoriedad", ya que las computadoras no son más que máquinas binarias, no pueden darnos "aleatoriedad verdadera". Después de un tiempo, la secuencia comenzará a repetirse. La búsqueda de una mejor generación de números aleatorios aún continúa, pero dicen que monitorear los niveles de ruido ambiental en una habitación es una buena manera de evitar la formación de patrones en la generación aleatoria.

Puede buscar this wiki article para obtener más información sobre la ciencia detrás de la generación de números aleatorios.

1

Este document es una muy buena redacción de generación de números pseudoaleatorios y tiene una serie de rutinas incluidas (en C). También se analiza la necesidad de una adecuada siembra de los generadores de números aleatorios (ver la regla 3). Particularmente útil para esto es el uso de/dev/randon/(si está en una máquina Linux).

Nota: las rutinas incluidas en este documento son mucho más fácil de codificar que el Mersenne Twister. Consulte también el generador WELLRNG, que se supone que tiene mejores propiedades teóricas, como alternativa al MT.

1

Lea el libro de rands de números aleatorios (libro de números aleatorios de monte carlo) ¡los números en él se generan aleatoriamente para usted! Mi abuelo trabajó para Rand.

2

Si está buscando un tratamiento teórico sobre números aleatorios, probablemente pueda echar un vistazo al Volumen 2 del El arte de la programación informática. Tiene un capítulo dedicado a números aleatorios. A ver si te ayuda.

1

La mayoría de los RNG (generadores de números aleatorios) requerirán un poco de inicialización. Esto usualmente es para realizar una operación de siembra y almacenar los resultados de los valores sembrados para su uso posterior. Este es un ejemplo de un método de siembra de una aleatoriedad que escribí para un motor de juego:

/// <summary> 
    /// Initializes the number array from a seed provided by <paramref name="seed">seed</paramref>. 
    /// </summary> 
    /// <param name="seed">Unsigned integer value used to seed the number array.</param> 
    private void Initialize(uint seed) 
    { 
     this.randBuf[0] = seed; 
     for (uint i = 1; i < 100; i++) 
     { 
      this.randBuf[i] = (uint)(this.randBuf[i - 1] >> 1) + i; 
     } 
    } 

Esto se llama desde el constructor de la clase de aleatorización. Ahora los números aleatorios reales se pueden rodar/calcular usando los valores sembrados antes mencionados. Esto es usualmente donde se aplica el algoritmo de aleatorización real. He aquí otro ejemplo:

/// <summary> 
    /// Refreshes the list of values in the random number array. 
    /// </summary> 
    private void Roll() 
    { 
     for (uint i = 0; i < 99; i++) 
     { 
      uint y = this.randBuf[i + 1] * 3794U; 
      this.randBuf[i] = (((y >> 10) + this.randBuf[i])^this.randBuf[(i + 399) % 100]) + i; 
      if ((this.randBuf[i] % 2) == 1) 
      { 
       this.randBuf[i] = (this.randBuf[i + 1] << 21)^(this.randBuf[i + 1] * (this.randBuf[i + 1] & 30)); 
      } 
     } 
    } 

Ahora los valores laminados se almacenan para su uso posterior en este ejemplo, pero esos números también se pueden calcular sobre la marcha. La ventaja de precalcular es un ligero aumento del rendimiento. Dependiendo del algoritmo utilizado, los valores transferidos podrían devolverse directamente o pasar por algunos cálculos de último minuto cuando así lo solicite el código. Aquí hay un ejemplo que lleva desde los valores prerolled y escupe un muy buen aspecto de números pseudo aleatorios:

/// <summary> 
    /// Retrieves a value from the random number array. 
    /// </summary> 
    /// <returns>A randomly generated unsigned integer</returns> 
    private uint Random() 
    { 
     if (this.index == 0) 
     { 
      this.Roll(); 
     } 

     uint y = this.randBuf[this.index]; 
     y = y^(y >> 11); 
     y = y^((y << 7) + 3794); 
     y = y^((y << 15) + 815); 
     y = y^(y >> 18); 
     this.index = (this.index + 1) % 100; 
     return y; 
    } 
2

Si usted está deseando manualmente, codificar, su propio generador aleatorio no puedo darle la eficiencia, sin embargo, puedo darte confiabilidad. De hecho, decidí escribir un código usando el tiempo para probar la velocidad de procesamiento de una computadora contando a tiempo y eso me convirtió en escribir mi propio generador de números aleatorios usando el algoritmo de conteo para módulo (el recuento es aleatorio). Por favor, pruébenlo y prueben las distribuciones numéricas dentro de un gran conjunto de pruebas. Por cierto, esto está escrito en python.

def count_in_time(n): 
    import time 
    count = 0 
    start_time = time.clock() 
    end_time = start_time + n 
    while start_time < end_time: 
     count += 1 
     start_time += (time.clock() - start_time) 
    return count 


def generate_random(time_to_count, range_nums, rand_lst_size): 
    randoms = [] 
    iterables = range(range_nums) 
    count = 0 
    for i in range(rand_lst_size): 
     count += count_in_time(time_to_count) 
     randoms.append(iterables[count%len(iterables)]) 
    return randoms 
Cuestiones relacionadas