2009-11-24 12 views
9

¿Cómo puedo hacer un RNG rápido (Generador de Números Aleatorios) en C# que admita llenar una matriz de bytes con un Valor Máximo (y/o un Valor mínimo)? Encontré esto http://www.codeproject.com/KB/cs/fastrandom.aspx pero no tengo estas características.Generador Aleatorio Rápido

+10

¿System.Random es demasiado lento? – driis

+0

Muy bien puede ser. Está llenando bytes, que es un caso muy especial. El código destinado a llenar bytes podría ser probablemente un orden de magnitud más rápido o más. Necesita _necesita esa velocidad? No lo sé. – Nosredna

+4

Sí, System.Random es demasiado lento. Tengo muchos muchos números aleatorios para generar. – tazzo

Respuesta

23

El hecho de que se está llenando con bytes enteros es lo suficientemente diferente de el caso de uso típico de System.Random que probablemente puedas superar si realmente lo necesitas.

System.Random está hecho para uso general. (De hecho, suelo encontrar aburridas las rutinas al azar del sistema cuando hago pruebas de velocidad y distribución sobre ellas). Hay casos en los que desearías algo más. Pero tienes que ser muy explícito sobre tus necesidades. ¿Qué rápido? ¿Qué estás dispuesto a renunciar?

Si realmente necesita "rápido", Marsaglia ha producido varios generadores de números aleatorios muy rápidos que se podrían adaptar a sus necesidades. Aquí hay algunos enlaces sobre uno de ellos, Xorshift:

El último aborda el hecho de que se está dirigiendo a bytes.

Solo he necesitado randoms súper rápidos algunas veces. En los juegos de consola con procesadores lentos donde el azar podría marcar la diferencia entre alcanzar el objetivo de velocidad de fotogramas y no golpearlo. ¿Cuál es tu caso de uso? Por supuesto, use System.Random si puede.

O bien, adapte la rutina a la que se vincula en su pregunta (que según el autor es 8 veces la velocidad de System.Random).)

+0

Ese último enlace fue bastante interesante de examinar, +1 –

+0

Gracias por su respuesta, el RNG debe ser lo más rápido posible, tengo muchos números aleatorios para generar en pocos segundos (10^9 y más). He tratado de adaptar la rutina en mi enlace, pero no he tenido éxito, ¿me pueden ayudar? – tazzo

+0

Hay muchas posibilidades. Imagine que ha configurado un buffer 4k de números aleatorios para un rango (digamos, 0-100). Use un generador de números aleatorios para elegir un desplazamiento y agarre, digamos 16 bytes de su lista. Luego genere otro desplazamiento y tome otros 16 bytes. Esto no será fantásticamente aleatorio, pero puede ser bastante aleatorio. A pesar de que te pregunte, no me has dicho a qué estás dispuesto a renunciar para obtener la velocidad. ¿Qué vas a hacer con todos estos números? – Nosredna

-3

Puede usar Reflector para descompilar System.Random en C#. Eso le daría el código C# de un generador de números aleatorios rápidos que cumpla con sus requisitos.

+3

En realidad, no ... el Framework está precompilado y optimizado, no puede competir con eso (hasta que también precompile su código). Al menos esa es la experiencia que hice (al tratar de superar el marco;)). – Bobby

+3

¿Y por qué exactamente haría eso? Presumiblemente, ya que él pregunta, Random es demasiado lento, de lo contrario usaría eso, ¿no? –

+0

@Bobby: deprimente, cierto. Precompilar el propio código no ayudará, sin embargo. –

12

System.Random es lo suficientemente rápido para casi cualquier uso típico. Si tiene problemas de rendimiento con un código que contiene llamadas System.Random, asegúrese de crear un perfil de su código antes de intentando crear un nuevo Random. Lo más probable es que sus problemas de rendimiento no estén en el marco, sino en su propio código.

Si llama a Random en un bucle, asegúrese de que no está creando una nueva instancia aleatoria con cada iteración, sino que está reutilizando una instancia Aleatoria común. Hacer esto mejorará el rendimiento porque no está creando nuevos objetos para que el GC lo limpie, y también mejorará la calidad de los números aleatorios que se generan.

+0

Mi código solo tiene que generar muchos números aleatorios en pocos segundos – tazzo

+22

Es asombroso cuántas de las respuestas de SO deciden discutir las necesidades del asker en lugar de responder la pregunta. – Nosredna

+1

@tazzo: ¿cuántos son muchos? ¿Cuáles son los requisitos específicos que buscas? @Nosredna: a veces responder la pregunta y ayudar al que pregunta son dos cosas diferentes. ¿Y quién está discutiendo? –

-1

utilizar los servicios criptográficos ....

RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider(); 
byte[] bytes= new byte[5]; 
crypto.GetBytes(bytes); 

por supuesto, esto sólo satisface el requisito de área de bytes ...

+5

No lo he cronometrado yo mismo, pero supongo que el RNGCryptoServiceProvider, que tiene la propiedad adicional de ser criptográficamente seguro, sería más lento que System.Random. – SoftMemes

+0

He comprobado RNGCryptoServiceProvider pero no se ajusta a mis necesidades, es reducir la velocidad y no permitir un máximo en números aleatorios generados. – tazzo

0

Si tiene un generador de números aleatorios que devuelve números del intervalo de la unidad, como el del artículo de Code Project que mencionó, primero puede generar un valor u usando ese generador y luego devolver a + (b-a)*u para obtener valores entre a y B.

+0

Su fórmula es incorrecta, si elijo A = 5 y B = 20 y U = 55 obtengo 5+ (20-5) * 55 = 830. La fórmula correcta es U/(UMAX + 1) * (B-A) + A, donde UMAX es el valor máximo de un número aleatorio. – tazzo

+1

Si el valor aleatorio u proviene del * intervalo de unidad *, es decir, entre 0 y 1, entonces la fórmula es correcta. En su ejemplo, u = 55 no es un número entre 0 y 1. –

Cuestiones relacionadas