En este momento estás viendo Generador de números aleatorios que genera solo un número aleatorio

 – Unity

Generador de números aleatorios que genera solo un número aleatorio – Unity

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.NextPor 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

Deja una respuesta