HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

Extending java.util.Random.nextInt(int) into nextLong(long)

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
randomnextlongnextintutilintolongjavaintextending

Problem

In java.util.Random the Oracle implementation of nextInt(int) is as follows:

public int nextInt(int n) {
    if (n > 31);

    int bits, val;
    do {
        bits = next(31);
        val = bits % n;
    } while (bits - val + (n-1) < 0);
    return val;
}


I have a need to do the same thing for longs, but this is not included as part of the class signature. So I extended the class to add this behavior. Here's my solution, and even though I'm pretty sure I have it right, bit-twiddling can subtly fluster even the best of devs!

import java.util.Random;

public class LongRandom extends Random {

    public long nextLong(long n) {
        if (n <= 0)
            throw new IllegalArgumentException("n must be positive");    

        if ((n & -n) == n)  // i.e., n is a power of 2
            return nextLong() & (n - 1); // only take the bottom bits

        long bits, val;
        do {
            bits = nextLong() & 0x7FFFFFFFL; // make nextLong non-negative
            val = bits % n;
        } while (bits - val + (n-1) < 0);
        return val;

    }
}


Have I introduced a subtle bug? Are there improvements to make? What might I need to watch out for?

Solution

Try it with n>2^32 and your code will fail. 0x7FFFFFFFL reduces your code to int, breaking your extension to long. You need to use the maximal value of long not int in your mask. i.e. 7FFFFFFFFFFFFFFFL.

Context

StackExchange Code Review Q#18727, answer score: 3

Revisions (0)

No revisions yet.