Java aleatorio siempre devuelve el mismo número cuando configuro la semilla?

Necesito ayuda con un generador de números aleatorios que estoy creando. Mi código es el siguiente (dentro de una clase llamada números):

public int random(int i){ Random randnum = new Random(); randnum.setSeed(123456789); return randnum.nextInt(i); } 

Cuando llamo a este método desde otra clase (para generar un número aleatorio), siempre devuelve el mismo número. Por ejemplo, si tuviera que hacer:

 System.out.println(numbers.random(10)); System.out.print(numbers.random(10)); 

siempre imprime el mismo número, por ejemplo, 5 5. ¿Qué debo hacer para que se impriman dos números diferentes, por ejemplo, 5 8?

Es obligatorio que establezca la semilla.

Gracias

Necesitas compartir la instancia Random() en toda la clase:

 public class Numbers { Random randnum; public Numbers() { randnum = new Random(); randnum.setSeed(123456789); } public int random(int i){ return randnum.nextInt(i); } } 

Si siempre configuras la semilla, siempre obtendrás la misma respuesta. Eso es lo que hace el establecimiento de la semilla.

Hay dos problemas que causan lo que ves. El primero es que el código establece un valor inicial para una instancia Aleatoria. El segundo es que el método instancia “aleatorio” instancia un nuevo objeto aleatorio y luego establece inmediatamente su semilla con la misma semilla cada vez. La combinación de estas dos garantías de que, por el mismo valor de i, el método “aleatorio” siempre devolverá el mismo valor y siempre será el primero en la secuencia que la semilla siempre genera.

Suponiendo que establecer la semilla es obligatorio, para obtener el siguiente valor en la secuencia en lugar del mismo primer valor de la secuencia cada vez, la instancia randnum de Random no puede tener su semilla establecida cada vez justo antes de que se llame su siguiente método. Para solucionarlo, mueva la instancia de randnum local variable de Random desde el scope del método de instancia aleatorio al ámbito de clase. En segundo lugar, establezca la semilla solo cuando se le asigne una instancia Aleatoria aleatoria o solo para obtener la misma secuencia de resultados para volver a comenzar. El método de instancia setSeed (semilla larga) de Class Random no se puede ejecutar en el scope de la clase, por lo que el constructor tiene que establecerlo usando el constructor Random con el parámetro seed largo. El siguiente código muestra los cambios:

 public class RandomDemo { // arbitrary example class name // lots of class related stuff may be here... // still inside the class scope... // private is a good idea unless an external method needs to change it private Random randnum = new Random(123456789L); // the seed guarantees it will always produce the same sequence // of pseudo-random values when the next methods get called // for unpredicable sequences, use the following constructor instead: // private Random randnum = new Random(); // lots of code may be here... // publicly exposed instance method for getting random number // from a sequence determined by seed 123456789L // in the range from 0 through i-1 public int randnum(int i) { // don't set the seed in here, or randnum will return the exact same integer // for the same value of i on every method call // nextInt(i) will give the next value from randnum conforming to range i return randnum.nextInt(i); } // end randnum // lots of more code may be here... } // end class RandDemo 

Lo anterior le dará una solución exacta a su problema exacto, como se establece. Sin embargo, usar una semilla obligatoria parece inusual, dado lo que hace.

Si esto es para un proyecto de clase o una prueba de software donde la secuencia debe ser predecible y repetible, tiene sentido establecer la semilla en un valor fijo. De lo contrario, cuestione la validez de establecer la semilla en algún valor predeterminado. A continuación, se explica más acerca de Random, semillas para Random y por qué hay una disposición para el suministro de una semilla.

Random tiene dos constructores:

 Random() 

y

 Random(long seed) 

y un método de instancia

 setSeed(long seed) 

que todos afectan la secuencia de números obtenida de una instancia aleatoria. El método de instancia,

 setSeed(long seed) 

establece el objeto Random en el mismo estado en el que habría estado si se hubiera instanciado con la misma semilla que el argumento constructor. Solo se utilizan los 48 bits de bajo orden de un valor inicial.

Si un objeto Random se instancia sin una semilla, la semilla será la misma que la hora del sistema en milisegundos. Esto garantiza que, a menos que se realicen instancias de dos objetos aleatorios en el mismo milisegundo, producirán diferentes secuencias pseudoaleatorias. Solo se usan los 48 bits de menor valor de la semilla. Esto causa secuencias pseudoaleatorias impredecibles. No es necesario y es un desperdicio de recursos de computación obtener una nueva instancia de Aleatorio cada vez que uno llama al siguiente método.

Los parámetros de semilla de Random se proporcionan para que uno pueda instanciar un objeto Random que produce una secuencia que es repetible. Para una semilla dada, se garantiza que la secuencia de valores en los siguientes métodos será la misma secuencia siempre que se use esa semilla. Esto es útil para probar software que utilizará secuencias pseudoaleatorias donde los resultados deben ser predecibles y repetibles. No es útil para crear diferentes secuencias pseudoaleatorias impredecibles en funcionamiento.

La afirmación “es obligatorio que establezca la semilla” niega cualquier imprevisibilidad de las secuencias pseudoaleatorias del objeto Random. ¿Esto es para un proyecto de clase o prueba de software donde los resultados tienen que ser los mismos para las mismas entradas al progtwig?

Establezca la semilla una vez en el inicio, en lugar de cada vez que desee un nuevo número aleatorio.

Lo que está utilizando no es un generador de números aleatorios, es un generador de números pseudoaleatorios. Los generadores de PRNG generan secuencias de números pseudoaleatorias, la semilla selecciona un punto de inicio en una secuencia (un PRNG puede generar una o varias secuencias).

¿Necesitas crear el new Random() dentro de tu método random(int i) ? Si está OBLIGADO a hacerlo de esa manera, podría usar, podría establecer la semilla a la hora actual, aunque eso no es a prueba de fallas, porque podría llamar a su numbers.random(10) tan rápido después del otro que lo haría terminan siendo la misma semilla Puede intentar tal vez usar nanoSeconds (System.nanoTime (), creo? Y si setSeed solo acepta int, multiplíquelo, supongo).

Sin embargo, lo que sugeriría, si se le permite hacerlo, es declarar su Random fuera de su método. Si instancia su variable aleatoria en, por ejemplo, su constructor de clase de number , puede establecer cualquier semilla y cada vez que llame a su método, le dará un nuevo número. (Serán los mismos conjuntos de números cada vez que reinicie su aplicación si usa una semilla constante; sin embargo, también podría usar el tiempo como semilla en este caso).

Finalmente, el último problema podría ser si declaras varias clases number al mismo tiempo. Todos tendrán la misma semilla al azar y te darán el mismo conjunto de números aleatorios. Si esto sucede, puede hacer un static Random en su clase principal y llamarlo en su clase de números. Sin embargo, esto unirá esas dos clases, pero funcionaría. Otra opción sería enviar un valor incrementado a su constructor de clase de number , para cada number usted instancia, y usar el valor que pase como semilla.

La segunda opción debería ser buena para ti, si te permiten hacerlo de esa manera.

Usualmente, Random no es realmente aleatorio sino pseudoaleatorio. Significa que toma una semilla dada y la usa para generar una secuencia de números que parece aleatoria (pero es totalmente predecible y se repite si se pone la misma semilla).

Si no pone semillas, entonces la primera semilla se tomará de una fuente variable (generalmente la hora del sistema).

Por lo general, se usará un valor con semilla para que repita los valores exactos (por ejemplo, para probar). Use Aleatorio sin semilla en su lugar.