0

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?

Radon Rosborough
  • 3,726
  • 1
  • 30
  • 42

1 Answers1

3

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.

Community
  • 1
  • 1
Andreas
  • 138,167
  • 8
  • 112
  • 195
  • The purpose of doing it myself is to implement a **reversible** random number generator, which implements a history and methods to step the state of the generator backwards and forwards. I investigated subclassing `Random` to do this, but it seemed like a hack to try to add all this functionality just by overriding `next`. Hence the separate class. – Radon Rosborough May 30 '16 at 15:51
  • `((long)next(26) << 27) + next(27)` is logically the same as `next(53)`, except that the `next()` method in `Random` returns an `int`, i.e. max 32 bits. `next(53)` is the same as `nextLong() & ((1L << 53) - 1)` or `nextLong() >>> (64 - 53)`, depending on whether you want to low or high 53 bits of the long. – Andreas May 30 '16 at 16:00