La clase aleatoria tiene un método para generar int aleatorio en un rango dado. Por ejemplo:
Random r = new Random();
int x = r.nextInt(100);
Esto generaría un número int más o igual a 0 y menos de 100. Me gustaría hacer exactamente lo mismo con un número largo.
long y = magicRandomLongGenerator(100);
La clase aleatoria solo tiene nextLong (), pero no permite establecer el rango.
java
random
range
long-integer
Vilius Normantas
fuente
fuente
java.util.Random
solo usa una distribución de 48 bits (ver detalles de implementación), por lo que no tendrá una distribución normal.Respuestas:
A partir de Java 7 (o Android API Nivel 21 = 5.0+) puede usar directamente
ThreadLocalRandom.current().nextLong(n)
(para 0 ≤ x <n) yThreadLocalRandom.current().nextLong(m, n)
(para m ≤ x <n). Vea la respuesta de @Alex para más detalles.Si está atascado con Java 6 (o Android 4.x) necesita usar una biblioteca externa (por ejemplo
org.apache.commons.math3.random.RandomDataGenerator.getRandomGenerator().nextLong(0, n-1)
, vea la respuesta de @mawaldne ), o implementar la suya propianextLong(n)
.De acuerdo con https://docs.oracle.com/javase/1.5.0/docs/api/java/util/Random.html
nextInt
se implementa comoEntonces podemos modificar esto para realizar
nextLong
:fuente
rng.nextLong() % n
dará valores uniformes (suponga que todos los bits son buenos). Puedes ignorar esa parte si quieres.m <= x <= n
, ¿cómo modificarías tu solución?m
yn
se puede obtener con un número aleatorio entre0
yn-m
, a continuación, añadirm
.ThreadLocalRandom
ThreadLocalRandom
Tiene unnextLong(long bound)
método.También tiene
nextLong(long origin, long bound)
si necesita un origen distinto de 0. Pase el origen (inclusive) y el límite (exclusivo).SplittableRandom
tiene los mismosnextLong
métodos y le permite elegir una semilla si desea una secuencia de números reproducible.fuente
El método estándar para generar un número (sin un método de utilidad) en un rango es usar el doble con el rango:
le dará un largo entre 0 (inclusive) y rango (exclusivo). Del mismo modo, si desea un número entre x e y:
le dará un largo desde 1234567 (inclusive) hasta 123456789 (exclusivo)
Nota: compruebe los paréntesis, porque la conversión a larga tiene mayor prioridad que la multiplicación.
fuente
bound
tendrá que ser menor que el entero más grande que se puede codificar en un doble, 2 ^ 53.Los métodos anteriores funcionan muy bien. Si está usando apache commons (org.apache.commons.math.random), consulte RandomData. Tiene un método: nextLong (largo inferior, largo superior)
http://commons.apache.org/math/userguide/random.html
http://commons.apache.org/math/api-1.1/org/apache/commons/math/random/RandomData.html#nextLong(long,%20long)
fuente
Use el operador '%'
Al usar el operador '%', tomamos el resto cuando se divide entre su valor máximo. Esto nos deja con solo números desde 0 (inclusive) hasta el divisor (exclusivo).
Por ejemplo:
fuente
if (max == min)
if (nextLong() >= 0)
min = 0
ymax = 2 * (MAX_LONG / 3)
, entonces tiene el doble de probabilidades de obtener un valor[0, MAX_LONG / 3]
que de obtener uno[MAX_LONG / 3, 2 * (MAX_LONG / 3)]
.nextLong
devuelve un valor negativo, el resto será negativo y el valor estará fuera del rango.Mejorando aún más la respuesta de kennytm: una implementación de subclase que tenga en cuenta la implementación real en Java 8 sería:
fuente
if ((bound & m) == 0) { r = (bound * r) >> (Long.SIZE - 1); }
Primero, es fácil demostrar con pruebas unitarias que esto realmente no produce números en el rango [0, límite]. En segundo lugar, es innecesariamente elaborado:r = r & m
lograría el resultado deseado, y eso es básicamente lo que hace la implementación actual de Java 8. Es posible que la implementación fuera diferente cuando se escribió esta respuesta, pero no pudo haber sido lo que se muestra.Si desea un pseudoaleatorio distribuido uniformemente largo en el rango de [0,
m
), intente usar el operador de módulo y el método de valor absoluto combinado con elnextLong()
método como se ve a continuación:¿Dónde
rand
está tu objeto aleatorio?El operador de módulo divide dos números y genera el resto de esos números. Por ejemplo,
3 % 2
es1
porque el resto de 3 y 2 es 1.Como
nextLong()
genera una pseudoaleatoria distribuida uniformemente en el rango de [- (2 ^ 48), 2 ^ 48) (o en algún lugar de ese rango), deberá tomar el valor absoluto de la misma. Si no lo hace, el módulo delnextLong()
método tiene una probabilidad del 50% de devolver un valor negativo, que está fuera del rango [0,m
).Lo que solicitó inicialmente fue un pseudoaleatorio distribuido uniformemente de largo en el rango de [0,100). El siguiente código lo hace:
fuente
Qué tal esto:
?
fuente
El siguiente método le devolverá un valor entre 10000000000 y 9999999999
fuente
Desde Java 8 API
Podría ser más fácil tomar la implementación real del documento API https://docs.oracle.com/javase/8/docs/api/java/util/Random.html#longs-long-long-long- lo están utilizando para generar longs stream. Y su origen puede ser "0" como en la pregunta.
fuente
De la página al azar :
Entonces, si desea obtener un
Long
, ya no obtendrá el rango completo de 64 bits.Sugeriría que si tienes un rango que se acerca a una potencia de 2, acumulas
Long
como en ese fragmento, así:para obtener un rango de 35 bits, por ejemplo.
fuente
Los métodos que usan
r.nextDouble()
deberían usar:fuente
fuente
Random
instancias a medida, no debe detectarThrowable
otras excepciones si no es necesario, debe registrar los errores con algún tipo de marco de registro (es decir, SLF4J) en lugar de usarprintStackTrace
.Si puede usar flujos de Java, puede intentar lo siguiente:
Esto generará números en el rango dado para largos.
fuente
Esto debería funcionar
fuente
// usa el tiempo del sistema como valor semilla para obtener un buen número aleatorio
// Bucle hasta obtener un número mayor o igual a 0 y menor que n
fuente
n
es 1 o digo 2? El bucle realizará muchas iteraciones.