rango - numeros aleatorios negativos y positivos en java
Java: nĂºmero largo aleatorio en el rango 0<= x<n (14)
ThreadLocalRandom
ThreadLocalRandom
tiene un nextLong(long bound)
.
long v = ThreadLocalRandom.current().nextLong(100);
También tiene nextLong(long origin, long bound)
si necesita un origen distinto de 0. Pase el origen (inclusive) y el límite (exclusivo).
long v = ThreadLocalRandom.current().nextLong(10,100); // For 2-digit integers, 10-99 inclusive.
SplittableRandom
tiene los mismos métodos nextLong
y le permite elegir una semilla si desea una secuencia reproducible de números.
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.
// usa la hora del sistema como valor inicial para obtener un buen número aleatorio
Random random = new Random(System.currentTimeMillis());
long x;
do{
x=random.nextLong();
}while(x<0 && x > n);
// Haz un bucle hasta obtener un número mayor o igual a 0 y menor que n
A partir de Java 7 (o Android API Level 21 = 5.0+) puede usar directamente ThreadLocalRandom.current().nextLong(n)
(para 0 ≤ x <n) y ThreadLocalRandom.current().nextLong(m, n)
( para m ≤ x <n). Ver la respuesta de @Alex para más detalles.
Si tiene problemas 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)
, consulte @mawaldne respuesta de @mawaldne ), o implementa tu propio nextLong(n)
.
De acuerdo con http://java.sun.com/j2se/1.5.0/docs/api/java/util/Random.html nextInt
se implementa como
public int nextInt(int n) {
if (n<=0)
throw new IllegalArgumentException("n must be positive");
if ((n & -n) == n) // i.e., n is a power of 2
return (int)((n * (long)next(31)) >> 31);
int bits, val;
do {
bits = next(31);
val = bits % n;
} while(bits - val + (n-1) < 0);
return val;
}
Entonces podemos modificar esto para realizar nextLong
:
long nextLong(Random rng, long n) {
// error checking and 2^x checking removed for simplicity.
long bits, val;
do {
bits = (rng.nextLong() << 1) >>> 1;
val = bits % n;
} while (bits-val+(n-1) < 0L);
return val;
}
Desde la página en Random :
El método nextLong se implementa por clase Random como si fuera por:
public long nextLong() { return ((long)next(32) << 32) + next(32); }
Debido a que la clase Random usa una semilla con solo 48 bits, este algoritmo no devolverá todos los valores largos posibles.
Entonces, si quieres obtener un Long
, ya no obtendrás el rango completo de 64 bit.
Sugeriría que si tienes un rango que está cerca de una potencia de 2, construyas el Long
como en ese fragmento, como este:
next(32) + ((long)nextInt(8) << 3)
para obtener un rango de 35 bits, por ejemplo.
El método estándar para generar un número (sin un método de utilidad) en un rango es simplemente usar el doble con el rango:
long range = 1234567L;
Random r = new Random()
long number = (long)(r.nextDouble()*range);
le dará un largo entre 0 (inclusive) y rango (exclusivo). Del mismo modo si quieres un número entre x y y:
long x = 1234567L;
long y = 23456789L;
Random r = new Random()
long number = x+((long)(r.nextDouble()*(y-x)));
le dará un largo desde 1234567 (inclusive) hasta 123456789 (exclusivo)
Nota: verifique paréntesis, porque el lanzamiento a largo tiene mayor prioridad que la multiplicación.
El siguiente método le devolverá un valor entre 10000000000 a 9999999999
long min = 1000000000L
long max = 9999999999L
public static long getRandomNumber(long min, long max){
Random random = new Random();
return random.nextLong() % (max - min) + max;
}
Los métodos anteriores funcionan bien. Si está utilizando apache commons (org.apache.commons.math.random), consulte RandomData. Tiene un método: nextLong (largo inferior, largo superior)
Los métodos que usan r.nextDouble()
deberían usar:
long number = (long) (rand.nextDouble()*max);
long number = x+(((long)r.nextDouble())*(y-x));
Mejorando aún más la respuesta de kennytm: Una implementación de subclase teniendo en cuenta la implementación real en Java 8 sería:
public class MyRandom extends Random {
public long nextLong(long bound) {
if (bound <= 0) {
throw new IllegalArgumentException("bound must be positive");
}
long r = nextLong() & Long.MAX_VALUE;
long m = bound - 1L;
if ((bound & m) == 0) { // i.e., bound is a power of 2
r = (bound * r) >> (Long.SIZE - 1);
} else {
for (long u = r; u - (r = u % bound) + m < 0L; u = nextLong() & Long.MAX_VALUE);
}
return r;
}
}
Muchas gracias por esta publicación. Es justo lo que necesitaba. Tuve que cambiar algo para obtener la parte que solía trabajar.
Obtuve lo siguiente (incluido arriba):
long number = x+((long)r.nextDouble()*(y-x));
para trabajar cambiándolo a:
long number = x+ (long)(r.nextDouble()*(y-x));
ya que (long)r.nextDouble()
siempre es cero.
Qué tal esto:
public static long nextLong(@NonNull Random r, long min, long max) {
if (min > max)
throw new IllegalArgumentException("min>max");
if (min == max)
return min;
long n = r.nextLong();
//abs (use instead of Math.abs, which might return min value) :
n = n == Long.MIN_VALUE ? 0 : n < 0 ? -n : n;
//limit to range:
n = n % (max - min);
return min + n;
}
?
Si desea una pseudoaleatoria distribuida uniformemente larga en el rango de [0, m
), intente utilizar el operador de módulo y el método de valor absoluto combinados con el método nextLong()
como se ve a continuación:
Math.abs(rand.nextLong()) % m;
Donde rand
es tu objeto aleatorio.
El operador de módulo divide dos números y genera el resto de esos números. Por ejemplo, 3 % 2
es 1
porque el resto de 3 y 2 es 1.
Dado que nextLong()
genera una pseudoaleatoria distribuida uniformemente en el rango de [- (2 ^ 48), 2 ^ 48) (o en algún lugar de ese rango), tendrá que tomar el valor absoluto de la misma. Si no lo hace, el módulo del método nextLong()
tiene un 50% de posibilidades de devolver un valor negativo, que está fuera del rango [0, m
).
Lo que inicialmente solicitó fue una pseudoaleatoria distribuida uniformemente en el rango de [0,100). El siguiente código lo hace:
Math.abs(rand.nextLong()) % 100;
Use el operador ''%''
resultingNumber = (r.nextLong() % (maximum - minimum)) + minimum;
Al usar el operador ''%'', tomamos el resto cuando lo dividimos por su valor máximo. Esto nos deja con solo números desde 0 (inclusive) hasta el divisor (exclusivo).
Por ejemplo:
public long randLong(long min, long max) {
return (new java.util.Random().nextLong() % (max - min)) + min;
}
public static long randomLong(long min, long max)
{
try
{
Random random = new Random();
long result = min + (long) (random.nextDouble() * (max - min));
return result;
}
catch (Throwable t) {t.printStackTrace();}
return 0L;
}