使用循环:
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