使用循环:
BigInteger randomNumber;
do {
randomNumber = new BigInteger(upperLimit.bitLength(), randomSource);
} while (randomNumber.compareTo(upperLimit) >= 0);
平均而言,这将需要少于两次迭代,并且选择将是统一的。
编辑:如果您的RNG昂贵,则可以通过以下方式限制迭代次数:
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'
在此版本中,循环不只一次(在2 ^ 100中少于一次机会,即,比主机在下一秒内自发着火的可能性要小)是不可能的。另一方面,该mod()操作的计算量很大,因此该版本可能比以前的版本慢,除非randomSource实例异常慢。