Java Random double in interval [-1000, 1000] - java

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) ;

Related

Generate random float, both bounds inclusive

I need to generate random real numbers in the range [-0.5, 0.5], both bounds inclusive.
I found various ways to generate similar ranges, like
-0.5 + Math.random()
But the upper bound is always exclusive, I need it inclusive as well. 0.5 must be inside the range.
One way to achieve this would be to create random int from -500 to 500 and then divide it by 1000.
int max = 500;
int min = -500;
int randomInt = rand.nextInt((max - min) + 1) + min;
float randomNum = randomInt / 1000.00f;
System.out.println(randomNum);
You can change the precision by adding and removing zeros from the integer boundaries and the divisor. (eG: create integers from -5 to +5 and divide by 10 for less precision)
A disadvantage of that solution is that it does not use the maximum precision provided by float/double data types.
I haven't seen any answer that uses bit-fiddling inside the IEEE-754 Double representation, so here's one.
Based on the observation that a rollover to a next binary exponent is the same as adding 1 to the binary representation (actually this is by design):
Double.longBitsToDouble(0x3ff0000000000000L) // 1.0
Double.longBitsToDouble(0x3ffFFFFFFFFFFFFFL) // 1.9999999999999998
Double.longBitsToDouble(0x4000000000000000L) // 2.0
I came up with this:
long l = ThreadLocalRandom.current().nextLong(0x0010000000000001L);
double r = Double.longBitsToDouble(l + 0x3ff0000000000000L) - 1.5;
This technique works only with ranges that span a binary number (1, 2, 4, 8, 0.5, 0.25, etc) but for those ranges this approach is possibly the most efficient and accurate. This example is tuned for a span of 1. For ranges that do not span a binary range, you can still use this technique to get a different span. Apply the technique to get a number in the range [0, 1] and scale the result to the desired span. This has negligible accuracy loss, and the resulting accuracy is actually identical to that of Random.nextDouble(double, double).
For other spans, execute this code to find the offset:
double span = 0.125;
if (!(span > 0.0) || (Double.doubleToLongBits(span) & 0x000FFFFFFFFFFFFFL) != 0)
throw new IllegalArgumentException("'span' is not a binary number: " + span);
if (span * 2 >= Double.MAX_VALUE)
throw new IllegalArgumentException("'span' is too large: " + span);
System.out.println("Offset: 0x" + Long.toHexString(Double.doubleToLongBits(span)));
When you plug this offset into the second line of the actual code, you get a value in the range [span, 2*span]. Subtract the span to get a value starting at 0.
You can adjust the upper bound by the minimal value (epsilon) larger than the maxium value you expect. To find the epsilon, start with any positive value and make it as small as it can get:
double min = -0.5;
double max = 0.5;
double epsilon = 1;
while (max + epsilon / 2 > max) {
epsilon /= 2;
}
Random random = ThreadLocalRandom.current();
DoubleStream randomDoubles = random.doubles(min, max + epsilon);
Edit: alternative suggested by #DodgyCodeException (results in same epsilon as above):
double min = -0.5;
double max = 0.5;
double maxPlusEpsilon = Double.longBitsToDouble(Double.doubleToLongBits(max) + 1L)
Random random = ThreadLocalRandom.current();
DoubleStream randomDoubles = random.doubles(min, maxPlusEpsilon);
Given HOW GOD SPIDERS answer, here is a ready to use function :
public static double randomFloat(double minInclusive, double maxInclusive, double precision) {
int max = (int)(maxInclusive/precision);
int min = (int)(minInclusive/precision);
Random rand = new Random();
int randomInt = rand.nextInt((max - min) + 1) + min;
double randomNum = randomInt * precision;
return randomNum;
}
then
System.out.print(randomFloat(-0.5, 0.5, 0.01));
#OH GOD SPIDERS' answer gave me an idea to develop it into an answer that gives greater precision. nextLong() gives a value between MIN_VALUE and MAX_VALUE with more than adequate precision when cast to double.
double randomNum = (rand.nextLong() / 2.0) / Long.MAX_VALUE;
Proof that bounds are inclusive:
assert (Long.MIN_VALUE/2.0)/Long.MAX_VALUE == -0.5;
assert (Long.MAX_VALUE/2.0)/Long.MAX_VALUE == 0.5;
Random.nextDouble gives a value in the range of [0, 1]. So to map that to a range of [-0.5, 0.5] you just need to subtract by 0.5.
You can use this code to get the desired output
double value = r.nextDouble() - 0.5;

How to generate random double number outside a specified range in 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.

Android Random Numbers Issue

I am generating random numbers and I am having a equal distribution issue. The first and last numbers in the range always have half the change of getting chosen because they don't have that possibility of being rounded to on both sides.
For example, if the user chooses a min of 1 and a max of 10, 1 and 10 will have a decreased chance of getting picked compared to the others.
Here is my current code:
double num = random.nextDouble() * (max - min) + min;
String finalNum = String.format("%." + precision + "f", num);
I know I could fix this by using a nextInt() instead but the problem is that I want to keep it a double because the user selects how many decimal places there will be.
Help is appreciated.
double min = 1.0;
double max = 10.0;
double rand = r.nextDouble();
//now we add 1 for the spread (we want the number to be from 0.5 to 10.5)
double range = max - min + 1;
rand *=range;
//now we shift by an offset of min-0.5;
rand += (min -0.5);
//now we round the number
int intRand = Math.round(rand);
you can use rand (double) for displaying your precision
and use intRand (int) for your integer random.

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.

Random numbers in Java when working with Android

I need to make a random number between 1 and 20, and based on that number (using "If - Then" statements), I need to set the image of an ImageView.
I know that in Objective-C, it goes like this:
int aNumber = arc4Random() % 20;
if (aNumber == 1) {
[theImageView setImage:theImage];
}
How can I do this in Java? I have seen it done this way, but I do not see how I can set the range of numbers (1-20, 2-7, ect).
int aNumber = (int) Math.random()
Docs are your friends
Random rand = new Random();
int n = rand.nextInt(20); // Gives n such that 0 <= n < 20
Documentation:
Returns a pseudorandom, uniformly distributed int value between 0 (inclusive) and the specified value (exclusive), drawn from this random number generator's sequence.
Thus, from this example, we'll have a number between 0 and 19
Math.random() returns an double from [0,1[.
Random.nextInt(int) returns an int from [0, int[.
You can try:
int aNumber = (int) (20 * Math.random()) + 1;
or
Random rand = new Random();
int n = rand.nextInt(20) + 1;
You can use Math.random() to generate a double between 0 and 1 non-inclusive. Android Javadoc here.

Categories

Resources