10

I ran into this problem today and I'm sure there is an elegant solution I am not thinking of.

Let's say I want to generate a random integer(or long) in Java with a specified number of digits, where this number of digits can change.

I.e. pass in a number of digits into a method, and return a random number with the specified number of digits

Ex.) N = 3, generate a random number between 100-999; N = 4, generate a random number between 1000-9999

private long generateRandomNumber(int n){

/*Generate a random number with n number of digits*/

}

My attempt so far (this works, but it seems messy)

private long generateRandomNumber(int n){

    String randomNumString = "";

    Random r = new Random();

    //Generate the first digit from 1-9
    randomNumString += (r.nextInt(9) + 1);

    //Generate the remaining digits between 0-9
    for(int x = 1; x < n; x++){
        randomNumString += r.nextInt(9);
    }

    //Parse and return
    return Long.parseLong(randomNumString);

}

Is there a better/more efficient solution than this?

*There are lots of solutions for generating random numbers in a specified range, I was more curious on the best way to generate random numbers given a set number of digits, as well as making the solution robust enough to handle any number of digits.

I did not want to have to pass in a min and max, but rather just the number of digits needed

Tony Scialo
  • 5,457
  • 11
  • 35
  • 52

4 Answers4

15
private long generateRandomNumber(int n) {
    long min = (long) Math.pow(10, n - 1);
    return ThreadLocalRandom.current().nextLong(min, min * 10);
}

nextLong produces random numbers between lower bound inclusive and upper bound exclusive so calling it with parameters (1_000, 10_000) for example results in numbers 1000 to 9999. Old Random did not get those nice new features unfortunately. But there is basically no reason to continue to use it anyways.

zapl
  • 63,179
  • 10
  • 123
  • 154
  • Ah. I missed this method, although it uses the same idea of bounds checking: `while (r < origin || r >= bound)` – Kedar Mhaswade May 13 '16 at 18:49
  • I was unaware of the ThreadLocalRandom. Do you recommend using this for random number generation in general? – Tony Scialo May 13 '16 at 18:57
  • @TonyScialo yes. http://stackoverflow.com/questions/23396033/random-over-threadlocalrandom (that is unless you need secure random) – zapl May 13 '16 at 19:00
5
public static int randomInt(int digits) {
    int minimum = (int) Math.pow(10, digits - 1); // minimum value with 2 digits is 10 (10^1)
    int maximum = (int) Math.pow(10, digits) - 1; // maximum value with 2 digits is 99 (10^2 - 1)
    Random random = new Random();
    return minimum + random.nextInt((maximum - minimum) + 1);
}
andrucz
  • 1,971
  • 2
  • 18
  • 30
2

You can simply disregard the numbers that are not in the required range. That way your modified pseudo random number generator guarantees that it generates a number in the given range uniformly at random:

public class RandomOfDigits {
    public static void main(String[] args) {
        int nd = Integer.parseInt(args[0]);
        int loIn = (int) Math.pow(10, nd-1);
        int hiEx = (int) Math.pow(10, nd);
        Random r = new Random();
        int x;
        do {
            x = r.nextInt(hiEx);
        } while (x < loIn);
        System.out.println(x);
    }
}
Kedar Mhaswade
  • 4,535
  • 2
  • 25
  • 34
0

Here is the way I would naturally write a method like this:

private long generateRandomNumber(int n){
    double tenToN = Math.pow(10, n),
           tenToNMinus1 = Math.pow(10, n-1);
    long randNum = (long) (Math.random() * (tenToN - tenToNMinus1) + tenToNMinus1);
    return randNum;
}
Matthew Diana
  • 1,106
  • 7
  • 14