Рандомизация BigInteger - PullRequest
       5

Рандомизация BigInteger

4 голосов
/ 17 сентября 2010

Я хочу рандомизировать BigInteger. Намерение состоит в том, чтобы выбрать число от 1 до 8180385048. Хотя, как я заметил, BigInteger (BitLen, Random) делает это от n до X 2 -1, я хотел бы получить непредсказуемое число. Я пытался создать метод, который бы это делал, но я продолжаю сталкиваться с ошибками и, наконец, поддался спросу здесь. : P У кого-нибудь есть предложения как это сделать?

Ответы [ 3 ]

5 голосов
/ 17 сентября 2010

Судя по документам Random.nextInt(int n), которые, очевидно, должны решить ту же проблему, они, похоже, пришли к выводу, что вы не можете добиться большего успеха, чем "повторная выборка, если она находится вне диапазона", но что Ожидается, что штраф будет незначительным.

Из документов:

Алгоритм немного хитрый. Он отклоняет значения, которые могут привести к неравномерному распределению (из-за того, что 2 31 не делится на n). Вероятность отклонения значения зависит от n. Худший случай - это n = 2 30 + 1, для которого вероятность отклонения равна 1/2, а ожидаемое количество итераций до завершения цикла равно 2.

Я бы посоветовал вам просто использовать рандомизирующий конструктор , который вы упомянули, и выполнять итерации, пока не достигнете значения, которое находится в диапазоне, например, вот так:

public static BigInteger rndBigInt(BigInteger max) {
    Random rnd = new Random();
    do {
        BigInteger i = new BigInteger(max.bitLength(), rnd);
        if (i.compareTo(max) <= 0)
            return i;
    } while (true);
}

public static void main(String... args) {
    System.out.println(rndBigInt(new BigInteger("8180385048")));
}

Для вашего конкретного случая (с max = 8180385048), вероятность повторения, даже один раз, составляет около 4,8% , так что не беспокойтесь: -)

1 голос
/ 17 сентября 2010

Создайте цикл и получите случайные BigInteger s минимальной битовой длины, которая охватывает ваш диапазон, пока вы не получите одно число в диапазоне Это должно сохранить распределение случайных чисел.

0 голосов
/ 17 сентября 2010

Повторение, если вне диапазона, как предлагается в других ответах, является решением этой проблемы. Однако, если вы хотите избежать этого, другой вариант - использовать оператор модуля:

BigInteger i = new BigInteger(max.bitLength(), rnd);
i = i.mod(max);                 // Now 0 <= i <= max - 1
i = i.add(BigInteger.ONE);      // Now 1 <= i <= max
...