Resigned June 2023
Resigned June 2023

Reputation: 4937

Using a random long to generate random doubles

I'm implementing my own random number generator, and the algorithm I'm using naturally gives me a nextLong() method. However, using this core method, I need to implement the other standard methods, such as nextLong(long), nextInt(), nextDouble(), and so on, in terms of nextLong(). For example:

public long nextLong(long n) {
    long bits, val;
    do {
        bits = (nextLong() << 1) >>> 1;
        val = bits % n;
    } while (bits - val + n - 1 < 0L);
    return val;
}

public int nextInt() {
    return (int)nextLong();
}

How can I implement nextDouble?

Upvotes: 0

Views: 153

Answers (1)

Andreas
Andreas

Reputation: 159086

Don't know what the purpose of doing it yourself is, but you could just do it the same way the built-in Random class does it for nextDouble(), as described in the javadoc:

The method nextDouble is implemented by class Random as if by:

public double nextDouble() {
    return (((long)next(26) << 27) + next(27))
      / (double)(1L << 53);
}

Since you don't have an int next(int bits) method, but you do have a nextLong() method, use the fact that ((long)next(26) << 27) + next(27) is equivalent to next(53). It was done the long way because the next(int) method returns an int, i.e. max. 32 bits.

To get 53 bits from a long, you can use either the low or high 53 bits, your choice:

long low53 = nextLong() & ((1L << 53) - 1);
long high53 = nextLong() >>> (64 - 53);

So, your code would be:

private static final double DOUBLE_UNIT = 0x1.0p-53; // 1.0 / (1L << 53)
public double nextDouble() {
    return (nextLong() >>> (64 - 53)) * DOUBLE_UNIT;
}

The DOUBLE_UNIT stuff is how Random actually does it internally, because multiplication is faster than division, e.g. see Floating point division vs floating point multiplication.

Upvotes: 3

Related Questions