c# .net random .net-1.1

c# - Cambio de implementación a.NET''s Random()



.net-1.1 (5)

Alternativamente, ¿podría sugerir el uso de la clase System.Security.Cryptography.RandomNumberGenerator para generar matrices de bytes aleatorios criptográficamente fuertes?

RandomNumberGenerator rng = RandomNumberGenerator.Create(); byte[] bytes = new byte[128]; rng.GetBytes(bytes);

Me uniré al resto de los comentarios y menciono que confiar en una implementación no documentada es malo. Más aún, si realmente está confiando en una "aleatoriedad" predecible, si está utilizando esto para algo que debería ser "seguro", es totalmente incorrecto.

Estoy migrando un método que se usa para decodificar de .NET Framework 1.1 a .NET Framework 4. Noté que la implementación de Random cambió. Así que dada la misma semilla, Random.NextBytes devuelve un resultado diferente.

Así que si ejecuto el siguiente código.

byte[] bytes = new byte[4]; System.Random random = new System.Random(50); random.NextBytes(bytes); for(int i=0; i< bytes.Length; i++) { Console.WriteLine("bytes[" + i + "] = " + bytes[i]); }

Bajo .NET Framework 1.1 devuelve:

bytes[0] = 216 bytes[1] = 124 bytes[2] = 183 bytes[3] = 58

Bajo .NET framework 4 devuelve:

bytes[0] = 154 bytes[1] = 49 bytes[2] = 183 bytes[3] = 48

¿Cuál es la mejor manera de resolver este problema?


Este no es un problema con Random , satisface perfectamente su interfaz documentada. Este es un problema con su software basándose en un detalle de implementación. Aprende de este error y no lo vuelvas a hacer .

En lo que respecta a solucionar el problema, puede implementar su propia versión de la generación de números pseudoaleatorios de 1.1 para decodificar y luego implementar un nuevo algoritmo de codificación / decodificación que no se basa en un comportamiento inestable (como la implementación de Random o GetHashCode ) para Tu nueva versión del software.


No hay respuesta aquí, pero a diferencia de muchas personas aquí, no creo que documentar un comportamiento ridículo sea suficiente para justificarlo.

Porque en primer lugar, ¿por qué proporcionarías un mecanismo de siembra? Bueno, te lo diré: para que siempre puedas reproducir una secuencia aleatoria de una sola semilla en lugar de tener que persistir quizás millones de números aleatorios. Tenga en cuenta que dije ''siempre'', y no ''hasta que actualice a la próxima versión de .NET''. Al no ser coherentes en todas las versiones, los generadores de números aleatorios .NET actuales no proporcionan esta funcionalidad. Microsoft debería haber hecho un mejor trabajo al implementar esto (o no haberlo implementado) en lugar de simplemente documentar el comportamiento defectuoso.

Y, por cierto, aunque el algoritmo es de hecho un detalle de implementación, ¿cómo puede llamarse el resultado de un método para llamar un detalle de implementación? ¿Debo realmente tener que consultar la documentación de cada método en el marco .NET para asegurarme de que en la próxima versión no me arriesgo a obtener un resultado diferente de concatenar dos cadenas o calcular una raíz cuadrada?

Entonces, en mi opinión, lo que tenemos aquí es simplemente un generador de números aleatorios mal implementado. Y, por supuesto, todo el problema podría haberse evitado fácilmente al darle un nombre diferente a la nueva funcionalidad (basada en la nueva implementación).


Si es absolutamente dependiente de la versión .NET 1.1 de Random, entonces lo único que se me ocurre es crear un nuevo conjunto que apunte a 1.1 y llamar a eso desde su aplicación .NET 4 actualizada.

Sin embargo, ¿puedes detallar por qué es tan esencial para ti mantener esta semilla? Puede haber una mejor manera


Solo puede usar Reflector para copiar la clase aleatoria de 1.1 mscorlib.

public class Random1_1 { // Fields private int inext; private int inextp; private const int MBIG = 0x7fffffff; private const int MSEED = 0x9a4ec86; private const int MZ = 0x0; private int[] SeedArray; // Methods public Random1_1() : this(Environment.TickCount) { } public Random1_1(int Seed) { this.SeedArray = new int[0x38]; int num2 = 0x9a4ec86 - Math.Abs(Seed); this.SeedArray[0x37] = num2; int num3 = 0x1; for (int i = 0x1; i < 0x37; i++) { int index = (0x15 * i) % 0x37; this.SeedArray[index] = num3; num3 = num2 - num3; if (num3 < 0x0) { num3 += 0x7fffffff; } num2 = this.SeedArray[index]; } for (int j = 0x1; j < 0x5; j++) { for (int k = 0x1; k < 0x38; k++) { this.SeedArray[k] -= this.SeedArray[0x1 + ((k + 0x1e) % 0x37)]; if (this.SeedArray[k] < 0x0) { this.SeedArray[k] += 0x7fffffff; } } } this.inext = 0x0; this.inextp = 0x15; Seed = 0x1; } public virtual int Next() { return (int)(this.Sample() * 2147483647.0); } public virtual int Next(int maxValue) { if (maxValue < 0x0) { throw new ArgumentOutOfRangeException("maxValue"); } return (int)(this.Sample() * maxValue); } public virtual int Next(int minValue, int maxValue) { if (minValue > maxValue) { throw new ArgumentOutOfRangeException("minValue"); } int num = maxValue - minValue; if (num < 0x0) { long num2 = maxValue - minValue; return (((int)((long)(this.Sample() * num2))) + minValue); } return (((int)(this.Sample() * num)) + minValue); } public virtual void NextBytes(byte[] buffer) { if (buffer == null) { throw new ArgumentNullException("buffer"); } for (int i = 0x0; i < buffer.Length; i++) { buffer[i] = (byte)(this.Sample() * 256.0); } } public virtual double NextDouble() { return this.Sample(); } protected virtual double Sample() { int inext = this.inext; int inextp = this.inextp; if (++inext >= 0x38) { inext = 0x1; } if (++inextp >= 0x38) { inextp = 0x1; } int num = this.SeedArray[inext] - this.SeedArray[inextp]; if (num < 0x0) { num += 0x7fffffff; } this.SeedArray[inext] = num; this.inext = inext; this.inextp = inextp; return (num * 4.6566128752457969E-10); } }

Probado y da la salida deseada.