Используйте цикл:
BigInteger randomNumber;
do {
randomNumber = new BigInteger(upperLimit.bitLength(), randomSource);
} while (randomNumber.compareTo(upperLimit) >= 0);
в среднем для этого потребуется менее двух итераций, и выбор будет равномерным.
Редактировать: Если ваш ГСЧ дорогой, вы можете ограничить количество итераций следующим образом:
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
не является исключительно медленным.