c# - repetidos - generar numeros aleatorios sin repetir en c




Generador de números aleatorios solo generando un número aleatorio (6)

1) Como dijo Marc Gravell, intente usar UN generador aleatorio. Siempre es bueno agregar esto al constructor: System.Environment.TickCount.

2) Un consejo. Digamos que desea crear 100 objetos y suponga que cada uno de ellos debería tener su propio generador aleatorio (útil si calcula las CARGAS de números aleatorios en un período de tiempo muy corto). Si hiciera esto en un bucle (generación de 100 objetos), podría hacerlo así (para garantizar la aleatoriedad total):

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);

Aclamaciones.

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);
}

Como lo llamo

byte[] mac = new byte[6];
for (int x = 0; x < 6; ++x)
    mac[x] = (byte)(Misc.RandomNumber((int)0xFFFF, (int)0xFFFFFF) % 256);

Si paso ese bucle con el depurador durante el tiempo de ejecución obtengo diferentes valores (que es lo que quiero). Sin embargo, si coloco un punto de interrupción dos líneas debajo de ese código, todos los miembros de la matriz "mac" tienen el mismo valor.

¿Por qué sucede eso?


Cada vez que ejecutes

Random random = new Random (15);

No importa si lo ejecutas millones de veces, siempre usarás la misma semilla.

Si utiliza

Random random = new Random ();

Usted obtiene una secuencia de números aleatorios diferente, si un hacker adivina la semilla y su algoritmo está relacionado con la seguridad de su sistema, su algoritmo está roto. Yo te ejecuto mult. En este constructor, la semilla se especifica mediante el reloj del sistema y, si se crean varias instancias en un período de tiempo muy corto (milisegundos), es posible que tengan la misma semilla.

Si necesitas números aleatorios seguros debes usar la clase.

System.Security.Cryptography.RNGCryptoServiceProvider

public static int Next(int min, int max)
{
    if(min >= max)
    {
        throw new ArgumentException("Min value is greater or equals than Max value.");
    }
    byte[] intBytes = new byte[4];
    using(RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
    {
        rng.GetNonZeroBytes(intBytes);
    }
    return  min +  Math.Abs(BitConverter.ToInt32(intBytes, 0)) % (max - min + 1);
}

Uso:

int randomNumber = Next(1,100);

Hay muchas soluciones, aquí una: si solo quiere un número, borre las letras y el método recibe un resultado aleatorio y la longitud.

public String GenerateRandom(Random oRandom, int iLongitudPin)
{
    String sCharacters = "123456789ABCDEFGHIJKLMNPQRSTUVWXYZ123456789";
    int iLength = sCharacters.Length;
    char cCharacter;
    int iLongitudNuevaCadena = iLongitudPin; 
    String sRandomResult = "";
    for (int i = 0; i < iLongitudNuevaCadena; i++)
    {
        cCharacter = sCharacters[oRandom.Next(iLength)];
        sRandomResult += cCharacter.ToString();
    }
    return (sRandomResult);
}

La solución de Mark puede ser bastante costosa ya que necesita sincronizarse cada vez.

Podemos evitar la necesidad de sincronización utilizando el patrón de almacenamiento específico de 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.


Para facilitar la reutilización a lo largo de su 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 luego usar instancia aleatoria estática con código como

StaticRandom.Instance.Next(1, 100);

Preferiría usar la siguiente clase para generar números aleatorios:

byte[] random;
System.Security.Cryptography.RNGCryptoServiceProvider prov = new System.Security.Cryptography.RNGCryptoServiceProvider();
prov.GetBytes(random);




random