views:

179

answers:

5

I am unsure about how to generate a random n digit integer in Java using the BigInteger class.

+3  A: 

The simplest way would probably to be to fill a char[] array with 5000 random digits, convert that to a string, and then call the BigInteger(String) constructor.

If any of those steps gives you problems, please give more details.

Alternatively, you could do something like this:

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);
}

I suspect that would be rather less efficient though.

You could reduce the number of steps required by generating nine random digits at a time, with rng.nextInt(1000000000).

Jon Skeet
Note that this will give you a random distribution between 1 and 10^5000, so some numbers produced by this won't be 5000 digits long. If a uniform distribution among all 5000 digits is needed, then the first digit should be made into a special case chosen by rng.nextInt(9)+1 .
oksayt
@oksayt: Yes, I nearly mentioned that... then decided not to be so picky ;)
Jon Skeet
int i; char[] num = new char[5000];Random R = new Random();for (i = 0; i < 5000; i++) { int j = R.nextInt(10) + 1; num[i] = (char) j;}String s = num.toString();BigInteger n = new BigInteger(s);
makaveli2178
I took your advise to fill a char[] array with 5000 random digits, convert that to a string, and then call the BigInteger(String) constructor (see code above). However, I get the following error: Exception in thread "main" java.lang.NumberFormatException: For input string: "[C" at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48) at java.lang.Integer.parseInt(Integer.java:449) at java.math.BigInteger.<init>(BigInteger.java:316) at java.math.BigInteger.<init>(BigInteger.java:451) at RandomNumber.main(RandomNumber.java:22)
makaveli2178
@makaveli2178: You should be adding '0' to the value, not 1. Otherwise you've got Unicode values 1-10 in your string.
Jon Skeet
I added '0' instead of one. so that part of the code inside the for loop now looks like this: num[i] = (char)(R.nextInt(10) + '0');and that works out well. However, the code: String s = num.toString(); is what doesnt seem to convert all the entries into a single string. How do i go about doing that?
makaveli2178
@makaveli2178: Well that will convert `num` into a string, but you haven't given nearly enough context to know what you're doing wrong. Please edit your question with a complete example.
Jon Skeet
Nevermind, I got it, I just needed String s = new String(num). Thanks a lot for your help though :)
makaveli2178
+2  A: 
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();
}

And then you can use it:

new BigInteger(getRandomNumber(10000))
Eyal Schneider
not bad, you need a special case for the first digit though
seanizer
@seanizer: if we want a uniform distribution on the range 1x..x - 9..9 then you are right. I assumed a uniform distribution on the complete range. +1 on your answer anyway :)
Eyal Schneider
A: 

Take a string with 5000 digits in it then convert it into BigInteger.

Dheeraj Joshi
+3  A: 

According to the docs, there is a constructor to do what you want in java 6: BigInteger(int, java.util.Random)

To that, you need only add a randomly selected 5000th digit-i.e. Use the rng constructor to 4999 digits, the add the last in via a separate random process. Actually, since you want to just sample performance for large values, you could generate the bits, and tack a one bit on the big end, rather than slave to decimal notation.

Carl
That gives a number of *bits* rather than *digits*, which will make it at least *slightly* fiddly if the OP wants a random distribution over 5000 digit numbers.. basically generate a random value which might be too big, and then repeat until a reasonable one comes along.
Jon Skeet
@Jon: see edit; if op is flexible on what "size" means for his question, 5000 bits (an so on) may be just as good as 5000 digits. Also, my phone sucks for answering questions.
Carl
Yes I want digits not Bits. I used that constructor you mentioned and then realized later that it just gives a number between 0 and 2^numbits - 1, not a 5000 DIGIT integer
makaveli2178
@makaveli2178: if your goal is to time operations on large numbers, the base of those numbers doesn't necessarily matter.
Carl
+1  A: 

Here are two versions, one takes a Random as parameter (in case you want to re-use it):

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));
}

The resulting BigInteger will always have the specified length.

seanizer