Reputation: 43
Why does generator.nextDouble()
in java return values only in the range from 0 to 1? The generator.nextInt()
method asks for a limiting value to be entered. Why is it not so with the Double
method?
Upvotes: 4
Views: 169
Reputation: 54639
From a conceptual point of view, one could argue that the interval between 0.0 and 1.0 is nice in a mathematical sense: It's trivial to compute an random number in an arbitrary range, given a random number between 0.0 and 1.0. Of course, one could insert utility methods in the Random
class, with equally trivial implementations:
public double nextDouble(double min, double max) {
return min + nextDouble() * (max - min);
}
Now one could ask why such a method is not the basic implementation in the first place. That is, why this method should be implemented based on the existing nextDouble()
method, and why there is no method that generates the value in the desired range "directly".
One important point has already been pointed out by Hoopje in his answer: The reason may be that the range between 0.0 and 1.0 is far better suited for representing values that are distributed uniformly.
When looking at (or rather: closely reading) the details about the IEEE 754 floating point number format, you will see that the density of values decreases when the values become larger.
When you start up an IEEE calculator and throw in the values for 0.0, 1.0 and 1.70141*10^38, then you will see their representations (for float
here - the statement analogously applies to double
) :
0.0 = 0x00000000 = 0
1.0 = 0x3F800000 = 1065353216
1.7...*10^38 = 0x7EFFFFFE = 2130706430
So in fact, the number of floating point numbers between 0.0 and 1.0 is basically the same as between 1.0 and 170141163178059628080016879768630000000.0. Implementing a good, uniform random number generator is not trivial, and creating a dedicated implementation for arbitrary ranges is hardly reasonably possible, considering the issue that the representable values themself are not uniformly distributed.
So for the range of 0.0 to 1.0 one can make the solid statement that the values are uniformly distributed. For other ranges, one would have to argue about what "uniformity" should actually mean for a certain range...
Upvotes: 2
Reputation: 12932
This answer is a bit speculative, but I guess the reason for this is that the random number generator is supposed to return pseadorandom doubles uniformly. It is not trivial at all to generate doubles uniformly, because doubles themselves are not uniformly distributed.
Ignoring the sign, doubles, or floating point numbers in general, are stored in the form m * 2^e
, where m
and e
have a fixed bit width, where m
is interpreted as a number between 0
(inclusive) and 1
(exclusive). This means that for high numbers the difference between two consecutive doubles is much greater than for small numbers. So, simply filling a double with random bits will not produce uniformly distributed pseudorandom numbers.
Instead, the solution is to fix the exponent e
to 0 and only choose a random mantissa m
, which yields a uniformly distributed double between 0 and 1. If you need random doubles in a different range, you can multiply the number with the desired range:
double randomDouble = rng.nextDouble() * range;
This will be good enough in practice when the range is not too high.
Upvotes: 2
Reputation: 180181
I take you to be asking about the motivation for the API design. That's somewhat speculative, but at least one good reason for the chosen design is that it is easy to implement correctly, while still serving the purpose of providing random numbers of any size (because you can scale the result).
Another reason could be that the result range of nextDouble()
follows long-established convention for floating-point PRNGs.
I appreciate that you find the difference between the integer and floating-point APIs disconcerting, but it is by no means the only difference between Java (and other) integer and FP APIs. These two kinds of numeric representations serve quite different purposes, which rarely intersect. There would little advantage to forcing them to have analogous APIs.
Upvotes: 1
Reputation: 7152
You can simply use this idiom to achieve what you want to do:
double max = 100000; // just an example
double randomDouble = (new Random()).nextDouble() * max;
Theoretically, I think there is no good reason why they cannot provide a method like this below. I think it was not provided simply because the above idiom is simple enough and no one complained :-)
/**
* Return a pseudorandom, uniformly distributed double value between
* 0 (inclusive) and the specified <code>max</code> value (exclusive)
* drawn from this random number generator's sequence.
* @param max
* @return
*/
double nextDouble(double max);
Upvotes: 0