4

Is it possible to have a user choose the number of digits of a random number, specifically a random Big Integer? For example if the user wants it to be 15 digits long the random number generator would only produce 15 digit long Big Integers.

Brian
  • 17,079
  • 6
  • 43
  • 66
Ryan Sayles
  • 3,389
  • 11
  • 56
  • 79
  • 1
    Have a look at Jon Skeet's answer to http://stackoverflow.com/questions/2290057/how-to-generate-a-random-biginteger-value-in-java – Don Roby Sep 15 '12 at 18:33

4 Answers4

5

You can use the constructor of BigInteger where you specify the number of binary digits: BigInteger(int numBits, Random rnd). You need roughly ten binary digits for each three decimal digits that the user wants. For example, if you need a 30-digit random BigInt, use 100 binary digits.

You can cut off the unnecessary digits by using remainder(10^30), and do it in a loop to ensure that the initial digit is not zero, ensuring the correct number of digits, like this:

Random rnd = new Random(123);
BigInteger tenPow30 = new BigInteger("10").pow(30);
BigInteger min = new BigInteger("10").pow(29);
BigInteger r;
do {
        r = new BigInteger(100, rnd).remainder(tenPow30);
} while (r.compareTo(min) < 0);
System.out.println(r);

Link to a demo.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • What is stopping the above code from generating a `0` as result, which is not a 30 digit number? – codaddict Sep 15 '12 at 18:50
  • @codaddict Arguably, it's a 30-digit random number with 30 zeros. You can always run it in a loop if you do not want leading zeros in your 30-digit number. – Sergey Kalinichenko Sep 15 '12 at 18:54
  • yes that check is needed not just for all zeroes but for any number generated below 1^30. – codaddict Sep 15 '12 at 18:56
  • @codaddict I added a loop to make sure the number does not have zeros in the leading positions. – Sergey Kalinichenko Sep 15 '12 at 19:02
  • Running it in a loop can make it loop infinitely with the proper random values. I agree with @codaddict that really, if `BigInteger.toString().length() < digits` is true, then this code will need to be run again. The probability that a loop would occur is literally almost 50%. – Brian Sep 15 '12 at 19:03
  • @Brian That is precisely what the code is doing without converting it to a string. The code can run infinitely only when the random number generator is infinitely bad. – Sergey Kalinichenko Sep 15 '12 at 19:08
  • @dasblinkenlight It's just not a great solution, is all, since the time taken is arbitrary and can't be computed without knowing the exact probability of the RNG. It would be better to simply check if the first digit was a `0` and put a different random, non-zero digit in its place if it is. – Brian Sep 15 '12 at 19:11
  • @Brian You can generate a 29-digit number an a 1-digit number then, and combine them into a 30-digit number without any checks. – Sergey Kalinichenko Sep 15 '12 at 19:19
  • I think I would prefer the 29 + 1 approach, because you know for sure you only need to run the code once. – Johanneke Jul 10 '13 at 08:27
4

You can always generate individual digits of the number randomly. This way for a 15 digit number you can generate 15 digits randomly and then form the number.

Another way:

Lets change the problem to generate random 5 digit number.

Min = 10000
Max = 99999

Now generate a random number between 0 and Max - Min which is 0 and 89999 and add it to Min.

Random = Min + Math.random() * (Max - Min)
codaddict
  • 445,704
  • 82
  • 492
  • 529
0

Here are the steps:

  1. Generate n numbers
  2. Combine them using a StringBuilder
  3. Create your number using BigInteger(String)

Here's some code:

public static BigInteger randomBigInt(int digits, Random rand) {
    StringBuilder sb = new StringBuilder(digits);

    // First digit can't be 0
    sb.append(rand.nextInt(9) + 1);

    int limit = digits - 1;
    for (int i = 0; i < limit; i++)
        sb.append(rand.nextInt(10));

    return new BigInteger(sb.toString());
}

This generates each digit separately and adds them to a StringBuilder (as opposed to an int or something, which can generate buffer overflow issues) and then uses the resultant String to create the BigInteger. Also notice that the first digit will never be 0.

Brian
  • 17,079
  • 6
  • 43
  • 66
  • Ah, this answer can compute numbers smaller than n digits. I'll change my answer. Sorry about that :X – Brian Sep 15 '12 at 18:55
-1

Using Random Generator like one here RandomUtil class you can make random numbers between some values and much more.

For example using this code will be 15 digits long in range of min=100000000000000 max=999999999999999:

BigInteger number = RandomUtil.getRandomBigInteger(new BigInteger("100000000000000"), new BigInteger("999999999999999"), false);
exp2Tapavicki
  • 311
  • 3
  • 15