Fiz assim mas dá sempre numeros entre -1 e 0,e quero entre -1 e 1.
public class Random{
public static void main(String[] args) {
System.out.println(Math.random()-1);
}
}
Fiz assim mas dá sempre numeros entre -1 e 0,e quero entre -1 e 1.
public class Random{
public static void main(String[] args) {
System.out.println(Math.random()-1);
}
}
Random r = new Random();
System.out.println(r.ints(-1, 2).findFirst().getAsInt());
O método Math.random() gera um valor do tipo double no intervalo 0 (inclusive) e 1 (exclusive), sendo assim, vc precisa ajustar isso, multiplicando por um valor que limitará superiormente o intervalo. Como você quer que o intervalo englobe o seu limite superior, vc precisa somar 1. Por exemplo:
double n1 = Math.random() * 5; // gera um double entre 0 (inclusive) e 5 (exclusive)
double n2 = Math.random() * ( 5 + 1 ); // gera um double entre 0 (inclusive) e 5 (inclusive)
A soma do 1 ali com o 5 é para você entender a ideia. Agora, vc precisa de um inteiro, então é só fazer um cast do double gerado para um int.
int n = (int) ( Math.random() * ( 5 + 1 ) ); // gera um int entre 0 (inclusive) e 5 (inclusive)
Como você quer variar o limite inferior também, vc precisa calcular quantas unidades existem entre seu limite inferior e o limite superior, ou seja, a distância entre esses dois valores. Por exemplo, se quiser gerar entre 5 e 12, vc precisa calcular a distância entre os dois (12 - 5 = 7). Fazendo:
int distancia = 12 - 5;
int n = (int) ( Math.random() * ( distancia ) ); // gera um valor entre 0 (inclusive) e 7 (exclusive)
Se vc somar o valor gerado à 5, você terá um valor entre 5 (inclusive) e 12 (exclusive), então vc precisa somar 1 à distância para englobar seu limite superior:
int distancia = 12 - 5;
int n = (int) ( Math.random() * ( distancia + 1 ) ); // gera um valor entre 0 (inclusive) e 7 (inclusive)
Agora, se vc somar o valor gerado à 5, você terá um valor entre 5 (inclusive) e 12 (inclusive), que é o que você quer. Pronto, basta colocar tudo isso em um método para parametrizar os limites e retornar o valor do intervalo fechado.
public static void main( String[] args ) {
for ( int i = 0; i < 10; i++ ) {
System.out.println( intervalRandom( -1, 1 ) );
}
}
public static int intervalRandom( int limiteInferior, int limiteSuperior ) {
if ( limiteInferior > limiteSuperior ) {
int temp = limiteSuperior;
limiteSuperior = limiteInferior;
limiteInferior = temp;
}
int distancia = limiteSuperior - limiteInferior;
return limiteInferior + (int) ( Math.random() * ( distancia + 1 ) );
}
A solução do @Lucas_Camara funciona e vai direto ao ponto usando streams, mas eu fiquei com a pulga atrás da orelha em relação à performance. Fiz um teste aqui meio bruto e é rápido igual, mas tem que tomar um certo cuidado, ainda mais se a essa geração de números que você precisa for ser utilizada massivamente.
public static void main( String[] args ) {
Random r = new Random();
long t1 = 0;
long t2 = 0;
long t3 = 0;
for ( int i = 0; i < 1000; i++ ) {
t1 = System.currentTimeMillis();
for ( int j = 0; j < 100000; j++ ) {
r.ints( -20000, 20000 ).findFirst().getAsInt();
}
t2 = System.currentTimeMillis();
for ( int j = 0; j < 100000; j++ ) {
intervalRandom( -20000, 20000 );
}
t3 = System.currentTimeMillis();
}
System.out.println( t2 - t1 );
System.out.println( t3 - t2 );
}
public static int intervalRandom( int limiteInferior, int limiteSuperior ) {
if ( limiteInferior > limiteSuperior ) {
int temp = limiteSuperior;
limiteSuperior = limiteInferior;
limiteInferior = temp;
}
int distancia = limiteSuperior - limiteInferior;
return limiteInferior + (int) ( Math.random() * ( distancia + 1 ) );
}
Só tome o cuidado de não instanciar um novo Random toda vez que for gerar o valor, senão o desempenho cai:
public static void main( String[] args ) {
long t1 = 0;
long t2 = 0;
long t3 = 0;
for ( int i = 0; i < 1000; i++ ) {
t1 = System.currentTimeMillis();
for ( int j = 0; j < 100000; j++ ) {
Random r = new Random();
r.ints( -20000, 20000 ).findFirst().getAsInt();
}
t2 = System.currentTimeMillis();
for ( int j = 0; j < 100000; j++ ) {
intervalRandom( -20000, 20000 );
}
t3 = System.currentTimeMillis();
}
System.out.println( t2 - t1 );
System.out.println( t3 - t2 );
}
public static int intervalRandom( int limiteInferior, int limiteSuperior ) {
if ( limiteInferior > limiteSuperior ) {
int temp = limiteSuperior;
limiteSuperior = limiteInferior;
limiteInferior = temp;
}
int distancia = limiteSuperior - limiteInferior;
return limiteInferior + (int) ( Math.random() * ( distancia + 1 ) );
}
Para finalizar, no benchmark poderia até ter feito a média dos tempos, mas eu preferi pegar a diferença só da última geração, pq teoricamente já houve tempo de rolar o warm-up do algoritmo.
Como Math.random()
retorna um double
, acredito que você queira um double
como resultado (mas se quiser um int
, use o que já foi sugerido acima).
Enfim, você pode usar um java.util.concurrent.ThreadLocalRandom
:
import java.util.concurrent.ThreadLocalRandom;
...
System.out.println(ThreadLocalRandom.current().nextDouble(-1, 1));
Ou um java.util.Random
(e neste caso eu sugiro que mude o nome da sua classe, para evitar colisão de nomes):
Random r = new Random();
double randomValue = (2 * r.nextDouble()) - 1;
// ou, a partir do Java 8
Random r = new Random();
double valor = r.doubles(-1, 1).findFirst().getAsDouble();
obrigado!!
obrigado!
Obrigado!