Как сгенерировать случайное целое число из n цифр в Java, используя класс BigInteger?

Я не уверен, как сгенерировать случайное n-значное целое число в Java с использованием класса BigInteger.


person makaveli2178    schedule 14.09.2010    source источник
comment
Хм... лучше всего построить его из совершенно случайных 32-битных или 64-битных чисел. Не уверен, что API позволяет это.   -  person Hamish Grubijan    schedule 14.09.2010
comment
Ммм... Я никогда этого не делал, но я считаю, что дезинфицирующее средство дало лучшее решение, чем мое. Вместо этого вы должны принять его ответ. Я полагаю, что когда вы говорите 5000-значные числа, вы имеете в виду, что первая цифра не 0, и мой ответ этому не соответствует.   -  person Eyal Schneider    schedule 15.09.2010


Ответы (6)


private static Random rnd = new Random();

public static String getRandomNumber(int digCount) {
    StringBuilder sb = new StringBuilder(digCount);
    for(int i=0; i < digCount; i++)
        sb.append((char)('0' + rnd.nextInt(10)));
    return sb.toString();
}

И тогда вы можете использовать его:

new BigInteger(getRandomNumber(10000))
person Eyal Schneider    schedule 14.09.2010
comment
@seanizer: если нам нужно равномерное распределение в диапазоне 1x..x - 9..9, то вы правы. Я предполагал равномерное распределение по всему диапазону. +1 к вашему ответу в любом случае :) - person Eyal Schneider; 14.09.2010
comment
По какой-то причине я иногда получаю длину 17 вместо 18 - person Jayshil Dave; 22.09.2015
comment
@JayshilDave: getRandomNumber(k) всегда будет возвращать строку из k цифр. Однако начальные цифры могут быть равны 0, поэтому компактное числовое представление может быть короче (фактически 10% результатов должны иметь длину k-1 или меньше). - person Eyal Schneider; 24.09.2015

Согласно документам, в java 6 есть конструктор, который делает то, что вы хотите: BigInteger(int, java.util.Random)

К этому вам нужно только добавить случайно выбранную 5000-ю цифру, т.е. Используйте конструктор rng для 4999 цифр, добавьте последнюю через отдельный случайный процесс. На самом деле, поскольку вы хотите просто сэмплировать производительность для больших значений, вы можете сгенерировать биты и прикрепить один бит к большому концу, а не подчиняться десятичной записи.

person Carl    schedule 14.09.2010
comment
Это дает количество битов, а не цифр, что сделает его, по крайней мере, слегка неудобным, если OP хочет случайного распределения более 5000 цифр. .. в основном генерировать случайное значение, которое может быть слишком большим, а затем повторять, пока не появится разумное значение. - person Jon Skeet; 14.09.2010
comment
@Jon: см. редактирование; если оператор гибок в отношении того, что означает размер для его вопроса, 5000 бит (и т. д.) могут быть такими же хорошими, как 5000 цифр. Кроме того, мой телефон отстой для ответов на вопросы. - person Carl; 14.09.2010
comment
Да, я хочу цифры, а не биты. Я использовал упомянутый вами конструктор, а затем понял, что он просто дает число от 0 до 2 ^ numbits - 1, а не целое число из 5000 DIGIT. - person makaveli2178; 14.09.2010
comment
@ makaveli2178: если ваша цель состоит в том, чтобы измерять время операций с большими числами, основание этих чисел не обязательно имеет значение. - person Carl; 14.09.2010

Вероятно, самым простым способом было бы заполнить массив char[] 5000 случайными цифрами, преобразовать его в строку, а затем вызвать конструктор BigInteger(String).

Если какой-либо из этих шагов вызывает у вас проблемы, сообщите подробнее.

Кроме того, вы можете сделать что-то вроде этого:

Random rng = new Random(); // But use one instance throughout your app
BigInteger current = BigInteger.ZERO;
for (int i = 0; i < 5000; i++) {
    BigInteger nextDigit = BigInteger.valueOf(rng.nextInt(10));
    current = current.multiply(BigInteger.TEN).add(nextDigit);
}

Хотя я подозреваю, что это будет менее эффективно.

Вы можете уменьшить количество необходимых шагов, генерируя девять случайных цифр за раз с помощью rng.nextInt(1000000000).

person Jon Skeet    schedule 14.09.2010
comment
Обратите внимание, что это даст вам случайное распределение от 1 до 10 ^ 5000, поэтому некоторые числа, полученные таким образом, не будут состоять из 5000 цифр. Если требуется равномерное распределение среди всех 5000 цифр, то первая цифра должна быть помещена в специальный регистр, выбранный rng.nextInt(9)+1 . - person oksayt; 14.09.2010
comment
@oksite: Да, я чуть не упомянул об этом... потом решил не быть таким придирчивым ;) - person Jon Skeet; 14.09.2010
comment
инт я; char[] num = новый char[5000]; Случайный R = новый Случайный(); for (i = 0; i ‹ 5000; i++) { int j = R.nextInt(10) + 1; число [я] = (знак) j; } Строка s = num.toString(); BigInteger n = новые BigInteger(s); - person makaveli2178; 14.09.2010
comment
Я последовал вашему совету, чтобы заполнить массив char[] 5000 случайными цифрами, преобразовать его в строку, а затем вызвать конструктор BigInteger(String) (см. код выше). Однако я получаю следующую ошибку: Исключение в основном потоке java.lang.NumberFormatException: для входной строки: [C at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48) at java.lang.Integer.parseInt(Integer. java:449) в java.math.BigInteger.‹init›(BigInteger.java:316) в java.math.BigInteger.‹init›(BigInteger.java:451) в RandomNumber.main(RandomNumber.java:22) - person makaveli2178; 14.09.2010
comment
@ makaveli2178: Вы должны добавить «0» к значению, а не 1. В противном случае в вашей строке будут значения Unicode 1–10. - person Jon Skeet; 14.09.2010
comment
Я добавил «0» вместо единицы. так что часть кода внутри цикла for теперь выглядит так: num[i] = (char)(R.nextInt(10) + '0'); и это работает хорошо. Однако код: String s = num.toString(); это то, что, похоже, не преобразует все записи в одну строку. Как мне это сделать? - person makaveli2178; 14.09.2010
comment
@ makaveli2178: Что ж, это преобразует num в строку, но вы не дали достаточно контекста, чтобы понять, что вы делаете неправильно. Пожалуйста, отредактируйте свой вопрос с полным примером. - person Jon Skeet; 14.09.2010
comment
Неважно, я понял, мне просто нужно было String s = new String(num). Хотя большое спасибо за помощь :) - person makaveli2178; 14.09.2010

Вот две версии, одна принимает Random в качестве параметра (на случай, если вы захотите использовать его повторно):

public static BigInteger getRandomNumber(final int digCount){
    return getRandomNumber(digCount, new Random());
}

public static BigInteger getRandomNumber(final int digCount, Random rnd){
    final char[] ch = new char[digCount];
    for(int i = 0; i < digCount; i++){
        ch[i] =
            (char) ('0' + (i == 0 ? rnd.nextInt(9) + 1 : rnd.nextInt(10)));
    }
    return new BigInteger(new String(ch));
}

Результирующий BigInteger всегда будет иметь указанную длину.

person Sean Patrick Floyd    schedule 14.09.2010

Если n находится в диапазоне от 1 до 12, помогает следующий метод.

private String getRandom(int length) {
    if (length < 1 && length > 12) {
        throw new IllegalArgumentException("Random number generator length should be between 1 to 12");
    }
    long nextLong = Math.abs(random.nextLong());
    return String.valueOf(nextLong).substring(0, length);
}

Еще одна вещь, которую следует отметить, это то, что это не очень хорошо протестированный код.

person venu88    schedule 10.04.2014

Возьмите строку с 5000 цифрами, а затем преобразуйте ее в BigInteger.

person Dheeraj Joshi    schedule 14.09.2010