Generador de números aleatorios que genera solo un número aleatorio
– UnityAssets3Free
hola , me llamo jorge y hoy os traigo
esta pregunta
tengo la siguiente función:
//Function to get random number
public static int RandomNumber(int min, int max)
Random random = new Random();
return random.Next(min, max);
¿Cómo llamo?
byte[] mac = new byte[6];
for (int x = 0; x < 6; ++x)
mac[x] = (byte)(Misc.RandomNumber((int)0xFFFF, (int)0xFFFFFF) % 256);
Si ejecuto este bucle a través del depurador durante el tiempo de ejecución, obtengo valores diferentes (que es lo que quiero). Sin embargo, si coloco un punto de interrupción dos líneas debajo de este código, todos los miembros del mac
matriz tienen el mismo valor.
¿Por que sucede?
14 respuestas 14
cada vez que lo haces new Random()
se inicializa usando el reloj. Esto significa que en un ciclo cerrado obtienes el mismo valor muchas veces. Debes mantener un solo Aleatorio instancia y seguir usando próximo en el mismo instancia.
//Function to get a random number
private static readonly Random random = new Random();
private static readonly object syncLock = new object();
public static int RandomNumber(int min, int max)
lock(syncLock) // synchronize
return random.Next(min, max);
Editar (ver comentarios): ¿por qué necesitamos un lock
¿aquí?
Básicamente, Next
cambiará el estado interno del Random
instancia. Si hacemos esto al mismo tiempo desde varios subprocesos, podría argumentar que «acabamos de hacer que el resultado sea aún más aleatorio», pero lo que estamos haciendo es potencialmente romper la implementación interna y también podríamos comenzar a obtener los mismos números de diferentes threads , lo que podría ser un problema, y podría no serlo. Asegurar lo que sucede internamente es el mayor problema; ya que Random
lo hace no hacer garantías de seguridad de cualquier hilo. Por lo tanto, hay dos enfoques válidos:
- Sincronizar para que no accedamos a la vez desde diferentes hilos
- usar diferentes
Random
instancias por hilo
Cualquiera puede estar bien; pero silenciando uno único instancia de varias personas que llaman al mismo tiempo es simplemente buscar problemas.
O lock
apunta al primero (y más simple) de estos enfoques; sin embargo, otro enfoque podría ser:
private static readonly ThreadLocal<Random> appRandom
= new ThreadLocal<Random>(() => new Random());
esto es por hilo, por lo que no necesita sincronizar.
Para facilitar la reutilización en toda la aplicación, una clase estática puede ayudar.
public static class StaticRandom
private static int seed;
private static ThreadLocal<Random> threadLocal = new ThreadLocal<Random>
(() => new Random(Interlocked.Increment(ref seed)));
static StaticRandom()
seed = Environment.TickCount;
public static Random Instance get return threadLocal.Value;
Puede usar y usar una instancia aleatoria estática con código como
StaticRandom.Instance.Next(1, 100);
La solución de Mark puede ser bastante costosa ya que necesita sincronizarse todo el tiempo.
Podemos eludir la necesidad de sincronización utilizando el patrón de almacenamiento específico del subproceso:
public class RandomNumber : IRandomNumber
private static readonly Random Global = new Random();
[ThreadStatic] private static Random _local;
public int Next(int max)
var localBuffer = _local;
if (localBuffer == null)
int seed;
lock(Global) seed = Global.Next();
localBuffer = new Random(seed);
_local = localBuffer;
return localBuffer.Next(max);
Mida las dos implementaciones y verá una diferencia significativa.
Mi respuesta desde aquí:
solo reiterando la solución correcta:
namespace mySpace
public static class Util
private static rnd = new Random();
public static int GetRandom()
return rnd.Next();
Entonces puedes llamar:
var i = Util.GetRandom();
en toda parte.
Si necesita estrictamente un verdadero método estático sin estado para generar números aleatorios, puede confiar en un Guid
.
public static class Util
public static int GetRandom()
return Guid.NewGuid().GetHashCode();
Será un poco más lento, pero puede ser mucho más aleatorio que Random.Next
Por lo menos desde mi experiencia.
Pero no:
new Random(Guid.NewGuid().GetHashCode()).Next();
La creación de objetos innecesarios lo ralentizará, especialmente en un bucle.
Y Nunca:
new Random().Next();
No solo es más lento (dentro de un ciclo), su aleatoriedad es… bueno, no muy bueno según yo…
Prefiero usar la siguiente clase para generar números aleatorios:
byte[] random;
System.Security.Cryptography.RNGCryptoServiceProvider prov = new System.Security.Cryptography.RNGCryptoServiceProvider();
prov.GetBytes(random);
1) Como dijo Marc Gravell, intente usar UN generador aleatorio. Siempre es bueno agregar esto al constructor: System.Environment.TickCount.
2) Una propina. Digamos que desea crear 100 objetos y suponga que cada uno de ellos debe tener su propio generador aleatorio (útil si calcula MUCHOS números aleatorios en un período de tiempo muy corto). Si lo hace en un bucle (generando 100 objetos), puede hacerlo así (para garantizar la total aleatoriedad):
int inMyRandSeed;
for(int i=0;i<100;i++)
inMyRandSeed = System.Environment.TickCount + i;
.
.
.
myNewObject = new MyNewObject(inMyRandSeed);
.
.
.
// Usage: Random m_rndGen = new Random(inMyRandSeed);
Salud.
nota: si aun no se resuelve tu pregunta por favor dejar un comentario y pronto lo podremos de nuevo , muchas gracias
por hoy,espero que te funcione