15

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

makaveli2178
  • 153
  • 1
  • 1
  • 6
  • Hm ... the best way is to build it out of completely random 32-bit or 64-bit numbers. Not sure if API allows that. – Hamish Grubijan Sep 14 '10 at 13:56
  • Mmm... I've never done that, but I believe that seanizer gave a better solution than mine. You should accept his answer instead. I suppose that when you say "5000 digit numbers", you mean that the first digit is not 0, and my answer doesn't comply with this. – Eyal Schneider Sep 14 '10 at 21:34

6 Answers6

16
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
  • 22,166
  • 5
  • 47
  • 78
  • @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 Sep 14 '10 at 15:27
  • For some reason i sometimes get a length of 17 instead of 18 – Jayshil Dave Sep 22 '15 at 08:25
  • @JayshilDave: getRandomNumber(k) will always return a string of k digits. However, the leading digits may be 0, so the compact numeric representation may be shorter (actually 10% of the results should be of length k-1 or less). – Eyal Schneider Sep 24 '15 at 20:03
5

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.

Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588
Carl
  • 7,538
  • 1
  • 40
  • 64
  • 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 Sep 14 '10 at 14:14
  • @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 Sep 14 '10 at 14:20
  • 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 Sep 14 '10 at 14:29
  • 1
    @makaveli2178: if your goal is to time operations on large numbers, the base of those numbers doesn't necessarily matter. – Carl Sep 14 '10 at 14:34
4

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
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    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 Sep 14 '10 at 14:09
  • 1
    @oksayt: Yes, I nearly mentioned that... then decided not to be so picky ;) – Jon Skeet Sep 14 '10 at 14:12
  • 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 Sep 14 '10 at 15:03
  • 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.(BigInteger.java:316) at java.math.BigInteger.(BigInteger.java:451) at RandomNumber.main(RandomNumber.java:22) – makaveli2178 Sep 14 '10 at 15:05
  • 1
    @makaveli2178: You should be adding '0' to the value, not 1. Otherwise you've got Unicode values 1-10 in your string. – Jon Skeet Sep 14 '10 at 15:23
  • 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 Sep 14 '10 at 19:53
  • @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 Sep 14 '10 at 19:54
  • Nevermind, I got it, I just needed String s = new String(num). Thanks a lot for your help though :) – makaveli2178 Sep 14 '10 at 19:55
2

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.

Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588
1

If n is between 1 to 12 then following method helps

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

One more thing to note is that it is not well tested code.

venu88
  • 41
  • 4
0

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

Dheeraj Joshi
  • 3,057
  • 8
  • 38
  • 55