I need to generate arbitrarily large random integers in the range 0 (inclusive) to n (exclusive). My initial thought was to call nextDouble
and multiply by n, but once n gets to be larger than 253, the results would no longer be uniformly distributed.
BigInteger
has the following constructor available:
public BigInteger(int numBits, Random rnd)
Constructs a randomly generated BigInteger, uniformly distributed over the range 0 to (2numBits - 1), inclusive.
How can this be used to get a random value in the range 0 - n, where n is not a power of 2?
BigInteger valueOf() Method in Java we can call this function by BigInteger. valueOf(long value) code. Parameter: This method accepts a single parameter value which is the value of the BigInteger to be created. Return Value: This method returns the BigInteger whose value is equal to value of long passed as parameter.
For example, to generate a random number between 1 and 10, we can do it like below. ThreadLocalRandom random = ThreadLocalRandom. current(); int rand = random. nextInt(1, 11);
and(BigInteger val) method returns a BigInteger whose value is bitwise-AND of two BigIntegers. This method returns a negative number if both of the BigIntegers are negative. The and() method applies bitwise-AND operation upon the current bigInteger and bigInteger passed as parameter.
Use a loop:
BigInteger randomNumber; do { randomNumber = new BigInteger(upperLimit.bitLength(), randomSource); } while (randomNumber.compareTo(upperLimit) >= 0);
on average, this will require less than two iterations, and the selection will be uniform.
Edit: If your RNG is expensive, you can limit the number of iterations the following way:
int nlen = upperLimit.bitLength(); BigInteger nm1 = upperLimit.subtract(BigInteger.ONE); BigInteger randomNumber, temp; do { temp = new BigInteger(nlen + 100, randomSource); randomNumber = temp.mod(upperLimit); } while (s.subtract(randomNumber).add(nm1).bitLength() >= nlen + 100); // result is in 'randomNumber'
With this version, it is highly improbable that the loop is taken more than once (less than one chance in 2^100, i.e. much less than the probability that the host machine spontaneously catches fire in the next following second). On the other hand, the mod()
operation is computationally expensive, so this version is probably slower than the previous, unless the randomSource
instance is exceptionally slow.
The following method uses the BigInteger(int numBits, Random rnd)
constructor and rejects the result if it's bigger than the specified n.
public BigInteger nextRandomBigInteger(BigInteger n) { Random rand = new Random(); BigInteger result = new BigInteger(n.bitLength(), rand); while( result.compareTo(n) >= 0 ) { result = new BigInteger(n.bitLength(), rand); } return result; }
The drawback to this is that the constructor is called an unspecified number of times, but in the worst case (n is just slightly greater than a power of 2) the expected number of calls to the constructor should be only about 2 times.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With