How to generate random double number outside a specified range in Java? - java

Is there a way to generate random double value outside a specified range?
I know there is one within the range:
Random r = new Random();
double randomValue = rangeMin + (rangeMax - rangeMin) * r.nextDouble();
I would require one that is outside the range e.g
the range is 20 - 50 and I would like a number below 20 or higher than 50.
Could someone please advise?

Maybe something like (for numbers 1-20 and 50-100):
Random r = new Random();
double randomValue = r.nextDouble()*70;
if(randomValue>20) randomValue+=30;
It is not resource expensive and easy to understand.

You can try somethink like this :
Random rnd = new Random();
double x=0;
do{
x = rnd.nextDouble()*100;
}while(x>20 && x<50 );
System.out.println(x);
}
You generate a random double ( need multiply by 100 because generate double return value between 0 and 1 ) and loop while result >20 and <50

If you want a double, any double, outside a specific range, then you you can take advantage of the fact that a double is represented by 64 bits, and you can convert any 64-bit value to a double using the Double.longBitsToDouble method:
public static void main(String[] args) {
Random r = new Random();
double d;
do {
d = Double.longBitsToDouble(r.nextLong());
} while (d >= 20 && d <= 50);
System.out.println(d);
}

First of all you always need some upper bound for the number you're generating, so 'above rangeMax' won't really do. What you basically want is to have a number generated that falls into one of two ranges [0,minRange] or [maxRange, maxValue].
You can either go with the 'lazy approach' which is just generating a value between 0 and maxValue and generate a new one until you get on that does not fall into the [minRange,maxRange] range or you could do a two step generation process, i.e. generate a random number that determines whether you generate a number in the lower range or the upper range, for instance:
public static void main(String[] args) {
double result = (new Random().nextInt(2)) == 0 ? generateInRange(0, 20) : generateInRange(50, Double.MAX_VALUE);
}
private static double generateInRange(double min, double max) {
return new Random().nextDouble() * (max-min) + min;
}
This does give you a 50/50 chance of ending up in the lower and upper range, so you might want to tweak that.

Related

Can i create different random numbers in one for loop in java [duplicate]

The following code is only producing a 0 ;-;
What am I doing wrong?
public class RockPaperSci {
public static void main(String[] args) {
//Rock 1
//Paper 2
//Scissors 3
int croll =1+(int)Math.random()*3-1;
System.out.println(croll);
}
}
Edit, Another Poster suggested something that fixed it.
int croll = 1 + (int) (Math.random() * 4 - 1);
Thanks, everyone!
You are using Math.random() which states
Returns a double value with a positive sign, greater than or
equal to 0.0 and less than 1.0.
You are casting the result to an int, which returns the integer part of the value, thus 0.
Then 1 + 0 - 1 = 0.
Consider using java.util.Random
Random rand = new Random();
System.out.println(rand.nextInt(3) + 1);
Math.random() generates double values between range - [0.0, 1.0). And then you have typecasted the result to an int:
(int)Math.random() // this will always be `0`
And then multiply by 3 is 0. So, your expression is really:
1 + 0 - 1
I guess you want to put parenthesis like this:
1 + (int)(Math.random() * 3)
Having said that, you should really use Random#nextInt(int) method if you want to generate integer values in some range. It is more efficient than using Math#random().
You can use it like this:
Random rand = new Random();
int croll = 1 + rand.nextInt(3);
See also:
Math.random() versus Random.nextInt(int)
All our mates explained you reasons of unexpected output you got.
Assuming you want generate a random croll
Consider Random for resolution
Random rand= new Random();
double croll = 1 + rand.nextInt() * 3 - 1;
System.out.println(croll);
public static double random()
Returns a double value with a positive sign, greater than or equal to 0.0 and less than 1.0. Returned values are chosen pseudorandomly with (approximately) uniform distribution from that range.
int croll =1+(int)Math.random()*3-1;
eg
int croll =1+0*-1;
System.out.println(croll); // will print always 0

Is Math.random() safe to use?

I have a method which is generating random integers. I don't want integers to be repeated, so I created this code -
int prevInt = 0;
private int randomInt() {
int random = (int) (Math.random() * 3);
//generate random numbers between 0 to 3 inclusive
if(random == prevInt)
return randomInt();
//if previous random number is equal to currently generated
//random number, then call this method again for a different
//random number
prevInt = random;
return random;
//else return the generated random number
}
Is the above code safe to use? At worst case scenario, can it be possible that all random integers generated by Math.random() * 3 are same?
private final Random random = new Random();
private int randomInt(final int prev, final int max) {
final int next = random.nextInt(max - 1);
if(next >= prev){
return next + 1;
}else{
return next;
}
}
This will return an int between 0 and max without the need to repeat.
public static double random()
Returns a double value with a positive sign, greater than or equal to 0.0 and less than 1.0. Returned values are chosen pseudorandomly with (approximately) uniform distribution from that range.
There are two principal means of generating random (really pseudo-random) numbers:
the Random class generates random integers, doubles, longs and so on,
in various ranges.
the static method Math.random generates doubles between 0 (inclusive)
and 1 (exclusive).
To generate random integers:
do not use Math.random (it produces doubles, not integers)
use the Random class to generate random integers between 0 and N.
To generate a series of random numbers as a unit, you need to use a single Random object - do not create a new Random object for each new random number.
Other alternatives are:
SecureRandom, a cryptographically strong subclass of Random
ThreadLocalRandom, intended for multi-threaded cases
please have a look at this post.
SO Reference 1,Reference 2
From the javadoc, Math.random() return a pseudo random and (approximately) uniform distributed number within the range.
So when you don't strict accuracy you may use it. Otherwise search for better solution.
try this trivial code and see for yourself
for (int ran = 0; ran < 10; ran++) {
int random = (int) (Math.random() * 3);
System.out.println(random);
}
Output in my case
2 2 0 2 1 0 0 0 2 1
First, I must point that your question title is not that clear. Safe can mean various thing. In this case I think you mean safety of algorithm of your code, not security nor only Math.random().
Unfortunately, your code is not algorithmically safe. Even if Math.random is safe, Your code has always positive possibility on running at any time: roughly speaking it means there are no guarantee that your code ends in finite time.
Assume you are taking random number among 4 numbers. If you are drawing random number excluding right before number, you're actually not drawing from 4 numbers: it's 3. I suggest another method:
int prevInt = -1;
private int randomInt() {
if (prevInt == -1) {
int random = (int) (Math.random() * 4);
//generate random numbers between 0 to 3 inclusive
} else if
int random = (int) (Math.random() * 3);
random = (random >= prevint) ? (random + 1) % 4 : random;
}
prevInt = random;
return random;
}
private void resetRandom() {
prevInt = -1;
//use when you want to reset information that you have 'before' result.
}
This algorithm ends within finite time. Concern about whether Math.Random() itself is dangerous or whatever will be explained by other nice guys.
Yes, it is safe but we never know what is going to happen, so we can simply multiply Math.random two times to maintain a good safety
int random = (int) (Math.random() * Math.random() * 3);

Generate a Double in the Double domain

According to this question, to create a Double number in a given range, you can use:
Random r = new Random();
double randomValue = rangeMin + (rangeMax - rangeMin) * r.nextDouble();
I'm trying to generate a double number in the double domain [Double.MIN_VALUE, Double.MAX_VALUE] using the same code mentioned above:
package test;
import java.util.Random;
public class Main {
public static void main(String[] args) {
double lower = Double.MIN_VALUE;
double upper = Double.MAX_VALUE;
Random rand = new Random();
for (int i = 0; i < 200; i++) {
double a = lower + (upper - lower) * rand.nextDouble();
System.out.println(a);
}
}
}
However, I'm getting just positive numbers even after many iterations:
1.436326007111308E308
2.7068601271148073E307
1.266896721067985E308
8.273233207049513E306
1.3338832492644417E308
8.584898485464862E307
1.260909190772451E308
1.5511066198317899E307
1.2083062753983258E308
2.449979496663398E307
7.333729592027637E307
7.832069948910962E307
8.493365260900201E307
5.158907971928131E307
3.126231202546818E307
1.3576316635349233E308
1.0991793636673692E308
6.991662398870649E307
My question is: How to generate a double number in the double range?
The results are not what you expected, because MIN_VALUE is the smallest possible positive double value. The smallest possible double value is -Double.MAX_VALUE (note the minus sign).
But you can not simply use lower = -Double.MAX_VALUE, because then, the difference will not be representable as a double, and will overflow.
A first idea would be something like
double d = random.nextDouble() * Double.MAX_VALUE;
if (random.nextBoolean()) d = -d;
to cover the full possible range.
EDIT: A (possibly minor) aside: The proposed method should cover the negative double values as well, and should be correct in the sense that each possible value appears either in its positive or in its negative form with equal probability. However, it will not be able to return the value Double.MAX_VALUE (because the value returned by Random#nextDouble() is strictly smaller than 1.0). But based on the implementation of nextDouble, there anyhow may be double values that will never appear in the output.
Double.MIN_VALUE is the smallest positive value that you can represent as a double.
it is not the largest negative number. that would be -Double.MAX_VALUE
As I said in the comment and others have also said, MIN_VALUE is positive. But even if you use -Double.MAX_VALUE, your computation will overflow double precision when computing upper - lower because the result will be two times the maximum double! One way around this is:
val = Random.nextDouble();
return (val < 0.5) ? (-2 * val) * Double.MAX_VALUE : (2 * (val - 0.5)) * Double.MAX_VALUE;

Java Random double in interval [-1000, 1000]

In java I have:
Random random = new Random();
double randomNum = random.nextDouble();
which creates a random number between 0 and 1. However I want a number between -1000 and 1000, how would I scale this?
Thanks
2 possibilities:
[less dense]: multiple your results by 2000, and subtract 1000
from the result. It won't be as 'dense' as possibility 2.
get a random int in range [-1000,999], and add a random double in
range [0,1].
Note that possibility 2 ensures better randomness and better 'density' of your numbers, at the cost of 2 random calls [which might be expansive, if it is an issue].
Um, maths?
double randomNum = (random.nextDouble()-0.5d) * 2000;
Random random = new Random();
double randomNum = (random.nextDouble() * 2000.0d) - 1000.0d;
Try this algorithm:
Generate a random value in the range 0 to 1.
multiply that value by 2000 (the size of the desired range).
subtract 1000 from the result of step 2 (move the value into the desired range).
This gives you a number on that range
double randomNum = (random.nextDouble() * 2000) -1000;
Here is a general function you could use to linearly rescale a number between zero and one (val01) to a different range (min..max):
public static double rescale(double val01, double min, double max) {
return val01 * (max - min) + min;
}
public static double doubleBetween(double start, double end) {
Random random = new Random();
// We need 64 bits because double have 53 bits precision, so int is too short
// We have now a value between 0 and Long.MAX_VALUE.
long value = -1L;
while (value < 0)
value = Math.abs(random.nextLong()); // Caution, Long.MIN_VALUE returns negative !
// Cast to double
double valueAsDouble = (double) value;
// Scale so that Long.MAX_VALUE is exactly 1 !
double diff = (end-start)/(double) Long.MAX_VALUE;
return start + valueAsDouble*diff;
}
This will give the correct interval including both ends with full double precision. doubles have a special -0.0 value (the negative zero) which will not be given by this routine.
Random random = new Random();
int randomNum = random.nextInt(2000) - 1000;
public static double randomInterval(double minValue,double maxValue){
Random random = new Random();
double r;
do {
r = random.nextDouble();
} while (r < minValue || r >= maxValue);
return r;
}
Example :
double a = randomInterval(-1000,1000) ;

Generate random numbers between two numbers

public class TestSample {
public static void main(String[] args) {
int a = Integer.parseInt(args[0]);
int b = Integer.parseInt(args[1]);
double ran = Math.random();
}
}
I don't want to use Random r = new Random(); class. Is there any other way to generate random numbers. I am just struck with what logic could be applied to generate random numbers between two numbers.
It's really easy... you only need to figure out which is the minimum value and what is the difference between the two numbers (let's call it diff). Then, you can scale the Math.random value (between 0 and 1) by multiplying by diff (now its range is between 0 and diff). Then, if you add the minimum value, your range is between min and min + diff (which is the other value)
int min = min(a,b);
int max = max(a,b);
int diff = max - min;
int result = min + diff * Math.random();
Consider using this code:
int a = Integer.parseInt(args[0]);
int b = Integer.parseInt(args[1]);
double ran = Math.random();
double random;
if(a < b)
random = (b-a)*ran + a;
else
random = (a-b)*ran + b;
This will work for a >= 0 and b >= 0 if you consider using negative number the logic sligtly changes
If you are expecting a double result, the simplest approach is
int a =
int b =
double result = (a-b)*Math.random() + b;
It doesn't matter which is greater as you get the same distribution.
However, if you want a random integer between 'a' and 'b' is a bit more complex.
int a =
int b =
int result = Math.floor((Math.abs(a-b)+1) * Math.random()) + Math.min(a, b);
The reason the result is different is that a random double between 0 and 1 will be just less than 1 i.e. [0.0, 1.0) However a random integer between 1 and 6 usually includes 1, 2, 3, 4, 5, 6 equally. As a decimal this is the round down of [0.0 ... 7.0)
You may get white noise from your microphone, and take any number from there. After that you may take any number from the given data, and do with it what you want. The example of getting data from the microphone can be found here.

Categories

Resources