11

I have seen posts which explains pretty much this question but they all used integer values and I honestly do not fully understand it hence this question:

I am trying to generate random numbers from the range (-1554900.101) to (52952058699.3098) in java and I was wondering if anyone could explain this to me as I really want to understand it.

My thoughts: will this be a right approach? 1) Generate a random integer number within my specified range 2) Divide the generated number by pi to get float/double random results

Thanks in advance.

isaiah
  • 311
  • 2
  • 5
  • 14

5 Answers5

38

Here's the idea. You want a random number in a range, let's say [-1.1,2.2], to start with a simple example. That range has length 3.3 since 2.2 - (-1.1) = 3.3. Now most "random" functions return a number in the range [0,1), which has length one, so we have to scale our random number into our desired range.

Random random = new Random();
double rand = random.nextDouble();
double scaled = rand * 3.3;

Now our random number has the magnitude we want but we must shift it in the number line to be between the exact values we want. For this step, we just need to add the lower bound of the entire range to our scaled random number and we're done!

double shifted = scaled + (-1.1);

So now we can put these parts together in a single function:

protected static Random random = new Random();
public static double randomInRange(double min, double max) {
  double range = max - min;
  double scaled = random.nextDouble() * range;
  double shifted = scaled + min;
  return shifted; // == (rand.nextDouble() * (max-min)) + min;
}

Of course, this function needs some error checking for unexpected values like NaN but this answer should illustrate the general idea.

maerics
  • 151,642
  • 46
  • 269
  • 291
  • If I am using `Double.MAX_VALUE` vs `Double.MIN_VALUE`, wouldn't line 3 in your last snippet go out of range? – SOFe Jul 07 '16 at 16:11
  • This answer is correct just for one value or sequence of values but without consider the case of use some step of range to get random values with. So, in case to get random sequence with some step the code above even covered by loop with end point may encourage the infinite loop. – Sergey V. Aug 19 '22 at 16:17
7
double lower = -1554900.101;
double upper = 52952058699.3098;
double result = Math.random() * (upper - lower) + lower;
highlycaffeinated
  • 19,729
  • 9
  • 60
  • 91
2

It should be something like:

double rnd = Math.random();

double result = ((long)(rnd * (529520586993098L - (-15549001010L) + 1)) -15549001010L) / 10000.0;

The + 1 will balance for the fact that the range is [0;1[ so the upper range is excluded.

We first try to find an "integer" (really long) range and we add 1 to balance the fact that the last number is excluded, so 529520586993098L + 15549001010L + 1, then we multiply it by rnd, cast it to long and subtract 15549001010L to shift it back and in the end divide it by 10000.0 to make it in the right "range".

This is probably more clear:

long range = 529520586993098L + 15549001010L + 1;

double temp = rnd * range;
long temp2 = (long)temp;
temp2 -= 15549001010L;

double result = temp2 / 10000.0;
xanatos
  • 109,618
  • 12
  • 197
  • 280
2

This not how I would do it.

  • Generate a random double. The result is between 0 and 1.
  • Multiply this number by (highLimit - lowLimit) (52952058699.3098 - -1554900.101)
  • Add the lowLimit (random + -1554900.101)

Here you go. You have a random number between low and high limit.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
1

Random.nextDouble returns a double in the range [0, 1[ so use that, multiply with your range size (52952058699.3098 + 1554900.101) and then offset the result (subtract 1554900.101) to get your number.

Not sure how exact you need this though, without doing some further analysis you might get numbers outside your range due to how doubles are handled.

Roger Lindsjö
  • 11,330
  • 1
  • 42
  • 53