2010-01-27 7 views
9

¿Es posible, desde .NET, imitar la aleatorización exacta que usa Java? Tengo una semilla, y me gustaría poder recibir los mismos resultados tanto en C# como en Java al crear un número aleatorio.C#/Java Number Aleatorización

+0

¿Y qué tan aleatorio es eso? ... Solo preguntando ... –

+0

@Filip: Creo que está implícito que solo quiere la aleatoriedad estocástica. –

+0

Supongo que tienes razón. –

Respuesta

5

Si tiene el código fuente de la clase java.util.Random para su implementación de Java, puede fácilmente transferirlo a .NET.

Si necesita ambas aplicaciones (Java y .NET) para usar un cierto generador de números aleatorios, será mejor que implemente uno en ambas plataformas y lo use, ya que la versión proporcionada por el sistema podría cambiar su comportamiento como resultado de una actualización. (se parece a la especificación Java describe con precisión el comportamiento de su PRNG.)

+0

Pero el algoritmo no es un detalle de implementación y es probable que cambie entre versiones/implementaciones ?IMO sería mejor implementar un algoritmo personalizado tanto en Java como en C# para obtener resultados consistentes. – dtb

+0

@dtb: Estaba pensando en lo mismo. Si va a ser temporal, para fines de prueba, eso sería suficiente. De lo contrario, sí, debes implementar la tuya. –

+4

@dtb: el algoritmo se especifica en la documentación de la clase Random de Java y, por lo tanto, es una especificación. Los detalles de la implementación pueden cambiar, pero dudo mucho que la secuencia real generada por ella sea en una versión futura. En todo caso, es más probable que agreguen un PRNG diferente en una clase separada. Pero dado el alcance previsto de Java y las bibliotecas maduras que realmente hacen un buen trabajo para la generación de números pseudoaleatorios, dudo que eso suceda de todos modos. – Joey

0

Bueno, puede buscar en el código fuente para Random.java y copiar el algoritmo, constantes, etc etc, pero aleatoria utiliza System.nanoTime en su constructor por lo que no obtendrá los mismos resultados.

De java.util.Random

aleatoria pública() { esto (++ + seedUniquifier System.nanoTime()); }

No me sorprendería en absoluto que la fuente en C# muestre algo similar.

Editar: Ignorar, como se ha señalado, el constructor que toma una semilla de entrada nunca accede al tiempo.

+2

Está usando la misma semilla para ambos, por lo que la semilla predeterminada en la implementación de Java es irrelevante. –

+0

Solo lo usa si no tiene una semilla, hay 2 constructores 'Random()' - No toma nada y usa 'Environment.TickCount' y' Random (int32 num) 'que toma su semilla en lugar de TickCount. –

0

¿Tal vez tendría sentido implementar su propio generador de números pseudoaleatorio simple? De esta manera, usted tiene el control completo y puede obtener la misma semilla que da los mismos resultados en ambos ambientes. Probablemente un poco más de trabajo que portar uno al otro sin embargo.

1

Si no necesita un generador de números pseudoaleatorios criptográficamente seguro, entonces yo iría por el Mersenne twister. Puede encontrar el código fuente para C# here y Java here.

+1

Sin embargo, esa no era la pregunta. Y 'java.util.Random' tampoco es criptográficamente seguro, así que obviamente no es h (es | er) preocupación ;-) – Joey

+1

No era la pregunta, pero desde *" imitar la aleatorización exacta que usa Java "* parece difícil imposible de hacer. Me centré en * "Me gustaría poder recibir los mismos resultados tanto en C# como en Java" *. –

-2

Otra opción podría ser escribir sus números aleatorios en un archivo una vez desde una plataforma y luego cargar sus números aleatorios para ambas plataformas desde ese archivo, o puede cargarlos desde un servicio como random.org

5

No necesita leer el código fuente. La fórmula es una de una sola línea y se da en la documentation for java.util.Random.

Aquí hay una traducción parcial:

[Serializable] 
public class Random 
{ 
    public Random(UInt64 seed) 
    { 
     this.seed = (seed^0x5DEECE66DUL) & ((1UL << 48) - 1); 
    } 

    public int NextInt(int n) 
    { 
     if (n <= 0) throw new ArgumentException("n must be positive"); 

     if ((n & -n) == n) // i.e., n is a power of 2 
      return (int)((n * (long)Next(31)) >> 31); 

     long bits, val; 
     do 
     { 
      bits = Next(31); 
      val = bits % (UInt32) n; 
     } 
     while (bits - val + (n - 1) < 0); 

     return (int) val; 
    } 

    protected UInt32 Next(int bits) 
    { 
     seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1); 

     return (UInt32)(seed >> (48 - bits)); 
    } 

    private UInt64 seed; 
} 

Ejemplo:

Random rnd = new Random(42); 
Console.WriteLine(rnd.NextInt(10)); 
Console.WriteLine(rnd.NextInt(20)); 
Console.WriteLine(rnd.NextInt(30)); 
Console.WriteLine(rnd.NextInt(40)); 
Console.WriteLine(rnd.NextInt(50)); 

de salida en ambas plataformas es 0, 3, 18, 4, 20.

Cuestiones relacionadas