Estoy un poco confundido, cómo hacerlo. Sé que puedo usar la clase Random para generar números aleatorios, pero no sé cómo especificar y generar un número de 8 bytes.Generar un número de 8 bytes en Java
Gracias, Vuk
Estoy un poco confundido, cómo hacerlo. Sé que puedo usar la clase Random para generar números aleatorios, pero no sé cómo especificar y generar un número de 8 bytes.Generar un número de 8 bytes en Java
Gracias, Vuk
Debe tener en cuenta que la clase java.util.Random
utiliza una semilla de 48 bits, por lo que no todos los valores de 8 bytes (secuencias de 64 bits) se pueden generar utilizando esta clase . Debido a esta restricción, le sugiero que use SecureRandom
y nextBytes
method en esta situación.
El uso es bastante similar a la solución java.util.Random
.
SecureRandom sr = new SecureRandom();
byte[] rndBytes = new byte[8];
sr.nextBytes(rndBytes);
Aquí es la razón por la cual una semilla de 48 bits no es suficiente:
Random
implementa un generador pseudo-aleatorio que significa que es determinista.Random
determina la secuencia futura de bits.Random
.Basado en @Peter Lawreys excellent answer (que merece más upvotes!): Aquí se presenta una solución para la creación de un × semilla de 48 bits con 2 java.util.Random
. Es decir, una instancia java.util.Random
capaz de generar todas las posibles long
s.
class Random96 extends Random {
int count = 0;
ExposedRandom extra48bits;
class ExposedRandom extends Random {
public int next(int bits) { // Expose the next-method.
return super.next(bits);
}
}
@Override
protected int next(int bits) {
if (count++ == 0)
extra48bits = new ExposedRandom();
return super.next(bits)^extra48bits.next(bits) << 1;
}
}
Se puede hacer ya sea con matriz de bytes de longitud 8:
byte[] byteArray = new byte[8];
random.nextBytes(byteArray);
o con una variable de tipo long
(que representa números de 8 bytes):
long randomLong = random.nextLong();
Tenga en cuenta que ninguna de estas dos alternativas es capaz de generar todo valores posibles de 8 bytes. Ver mi respuesta – aioobe
@aioobe: ¿puedes explicar por qué? He leído los documentos y he leído la implementación y todavía no entiendo bien. Existe un algoritmo bastante complejo (basado en matemática), y según tengo entendido, genera valores dependientes. Y si es verdad, entonces una instancia aleatoria realmente no genera todos los valores posibles de longs. Pero diferentes 'Aleatorios' (con diferentes" puntos de inicio ") sí lo hacen. ¿Estoy en lo cierto? – Roman
Actualizado mi respuesta. – aioobe
Un poco de ajuste desde el código here:
import java.util.Random;
/** Generate 10 random integers in the range 0..99. */
public final class RandomByte {
public static final void main(String... aArgs){
log("Generating 10 random integers in range 0..255.");
//note a single Random object is reused here
Random randomGenerator = new Random();
for (int idx = 1; idx <= 10; ++idx){
int randomInt = randomGenerator.nextInt(256);
// int randomInt = randomGenerator.nextBytes(256);
log("Generated : " + randomInt);
}
log("Done.");
}
private static void log(String aMessage){
System.out.println(aMessage);
}
}
leer un poco más lejos: Math.random() versus Random.nextInt(int)
Tenga en cuenta que la clase 'Random' es incapaz de generar todos los valores posibles de 8 bytes. – aioobe
El tipo long
es un entero de 8 bytes, por lo Random.nextLong()
parece hacer lo que quiera. O si necesita una matriz de bytes como resultado:
byte[] result = new byte[8];
Random.nextBytes(result);
Tenga en cuenta que la clase 'Random' es incapaz de generar todas las longitudes posibles. – aioobe
Estoy de acuerdo con @aioobe 'punto acerca de Random con una semilla de 48 bits. SecureRandom es una mejor solución. Sin embargo, para responder a las preguntas del OP sobre cómo usar la clase Random y aun así permitir todos los posibles valores de 8 bytes, se debe restablecer el seed periódicamente.
int counter = 0;
Random rand = new Random();
Random rand2 = new Random();
if (++counter == 0) rand = new Random(); // reset every 4 billion values.
long randomLong = rand.nextLong()^rand2.nextLong() << 1;
Al azar solo permite una secuencia de 2^47 valores largos. Al usar dos generadores aleatorios, uno que sigue dando saltos en la secuencia, obtienes dos 2^47 * 2^47 valores posibles. El uso de < < 1 es para evitar el impacto de tener ambos randoms con la misma semilla (en cuyo caso^produciría 0 para 4 mil millones de valores en una fila)
+1, Gran respuesta. Notas interesantes sobre el reinicio y el cambio a la izquierda Me gustaría que la respuesta sea aún mejor si encapsulaste la instancia Aleatoria en una subclase anónima de Aleatorio. – aioobe
¿No crearán los dos objetos aleatorios exactamente los mismos números aleatorios ya que ambos tendrán la misma semilla? (es decir, en una computadora veloz System.currentTimeMillis() será la misma para ambos?) –
En las versiones anteriores de Java, eso es cierto. Desde Java 5.0, Random usa System.nanoTime() y un contador AtomicLong. –
no es bueno dejar el mismo comentario en cada respuesta. – Roman
¿Por qué no? Creo que está bien. Se aplica a cada respuesta que comenté. – aioobe
Mi solución intuitiva habría sido generar dos valores de 4 bytes. Si te entiendo correctamente, esto no funcionaría porque los dos valores se excluirían (o al menos no sería probable) de ser igual cuando se usa el mismo generador dos veces. P.ej. ¿FF FF no sería tan probable como FF AA? No sé cómo se implementan los PRG, así que esto me sorprendió ya que esperaría que cada número fuera (pseudo-) independiente de los números anteriores. – zockman