Creating a Random BigInteger in Java

Java provides a custom class named BigInteger for handling very large integers (numbers which require more than 64 bits). BigInteger provides a constructor using which you can create a random BigInteger value.

public BigInteger(int numBits, Random rnd)

Constructs a randomly generated BigInteger, uniformly distributed over the range 0 to (2^numBits - 1), inclusive. The uniformity of the distribution assumes that a fair source of random bits is provided in rnd. Note that this constructor always constructs a non-negative BigInteger.

Random BigInteger Example in Java

The following random BigInteger example program creates a value between 0 and 15,

import java.math.BigInteger;
import java.util.Random;

public class RandomBigInteger {

    public static void main(String[] args) {
        BigInteger result = getRandomBigInteger();
        System.out.println(result);
    }
    public static BigInteger getRandomBigInteger() {
        Random rand = new Random();
        BigInteger result = new BigInteger(4, rand); // (2^4-1) = 15 is the maximum value
        return result;
    }
    
}

This works only if the maximum value of the random number you need is (2^n - 1). What if you need to generate random BigInteger between 0 and x where x can be any value?

The easiest solution is to generate random BigInteger between 0 and (2^n - 1) where n is the bit length for x and then ignore values whenever it is bigger than x.

For example, Assume you want to generate random BigInteger values between 0 and 13. The bit length for 13 is 4. Hence find a random number between 0 and 15 and then ignore the value if it is above 13.

import java.math.BigInteger;
import java.util.Random;

public class RandomBigInteger {

    public static void main(String[] args) {
        BigInteger result = getRandomBigInteger();
        System.out.println(result);
    }
    public static BigInteger getRandomBigInteger() {
        Random rand = new Random();
        BigInteger upperLimit = new BigInteger("13");
        BigInteger result;
        do {
            result = new BigInteger(upperLimit.bitLength(), rand); // (2^4-1) = 15 is the maximum value
        }while(result.compareTo(upperLimit) >= 0);   // exclusive of 13
        return result;
    }
    
}

The obvious drawback of this approach is that sometimes the loop will execute twice in turn invoking the random number generator twice. So if the random number generator passed is computationally intensive, this will affect the performance when generating a large number of random BigIntegers.