15

I am trying with below code to generate 10 digits unique random number. As per my req i have to create around 5000 unique numbers(ids). This is not working as expected. It also generates -ve numbers. Also sometimes one or two digits are missing in generated number resulting in 8 or 9 numbers not 10.

public static synchronized  List generateRandomPin(){

    int START =1000000000;
    //int END = Integer.parseInt("9999999999");
    //long END = Integer.parseInt("9999999999");
    long END = 9999999999L;

    Random random = new Random();

    for (int idx = 1; idx <= 3000; ++idx){
        createRandomInteger(START, END, random);
    }

    return null;
}


private static void createRandomInteger(int aStart, long aEnd, Random aRandom){
    if ( aStart > aEnd ) {
      throw new IllegalArgumentException("Start cannot exceed End.");
    }
    //get the range, casting to long to avoid overflow problems
    long range = (long)aEnd - (long)aStart + 1;
    logger.info("range>>>>>>>>>>>"+range);
    // compute a fraction of the range, 0 <= frac < range
    long fraction = (long)(range * aRandom.nextDouble());
    logger.info("fraction>>>>>>>>>>>>>>>>>>>>"+fraction);
    int randomNumber =  (int)(fraction + aStart);    
    logger.info("Generated : " + randomNumber);

  }
Nick
  • 11,475
  • 1
  • 36
  • 47
RajaShanmugam
  • 185
  • 1
  • 3
  • 7

10 Answers10

46

So you want a fixed length random number of 10 digits? This can be done easier:

long number = (long) Math.floor(Math.random() * 9_000_000_000L) + 1_000_000_000L;

Note that 10-digit numbers over Integer.MAX_VALUE doesn't fit in an int, hence the long.

njzk2
  • 38,969
  • 7
  • 69
  • 107
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • 1
    Intuitively, I feel that (long) Math.floor(Math.random() * 9000000000L) can yield all possible longs in the range [0,9000000000L), but is there a proof or counter-proof for it? A question to ponder over as I lay in bed.. – blizpasta Mar 16 '11 at 17:21
  • 1
    Hi BalusC, is there a reason why you use `9000000000L` instead of `9999999999L`? – Thang Pham Aug 03 '11 at 20:58
  • @Harry: The requirement states 10 digits, not 11 digits. – BalusC Aug 03 '11 at 21:00
  • @BalusC what to use instead of `9000000000L` for a 12 digit number ? – mukund Jan 23 '14 at 08:47
  • @mukund: just add two more zeroes to end of both longs. – BalusC Jan 23 '14 at 08:48
  • @blizpasta, in addition one also has to ask whether they are all equally likely, the multiplication combined with finite precision/rounding might skew the results. – the8472 Jul 11 '16 at 13:08
  • @BalusC How can make sure this logic always Generate Unique number – Onic Team Mar 18 '19 at 07:34
  • @BalusC : Actually i want to store this number as a account number so one account dose not matched with any other account number in future – Onic Team Mar 18 '19 at 07:37
  • **Note : - I don't want to check generated unique number matched with existing account number in my database** is it possible? – Onic Team Mar 18 '19 at 07:49
  • 1
    Just put unique constraint on database column, and regenerate number when unique constraint violation exception is thrown during insert. – BalusC Jan 10 '20 at 09:34
9

I think the reason you're getting 8/9 digit values and negative numbers is that you're adding fraction, a long (signed 64-bit value) which may be larger than the positive int range (32-bit value) to aStart.

The value is overflowing such that randomNumber is in the negative 32-bit range or has almost wrapped around to aStart (since int is a signed 32-bit value, fraction would only need to be slightly less than (2^32 - aStart) for you to see 8 or 9 digit values).

You need to use long for all the values.

   private static void createRandomInteger(int aStart, long aEnd, Random aRandom){
    if ( aStart > aEnd ) {
      throw new IllegalArgumentException("Start cannot exceed End.");
    }
    //get the range, casting to long to avoid overflow problems
    long range = aEnd - (long)aStart + 1;
    logger.info("range>>>>>>>>>>>"+range);
    // compute a fraction of the range, 0 <= frac < range
    long fraction = (long)(range * aRandom.nextDouble());
    logger.info("fraction>>>>>>>>>>>>>>>>>>>>"+fraction);
    long randomNumber =  fraction + (long)aStart;    
    logger.info("Generated : " + randomNumber);

  }
typo.pl
  • 8,812
  • 2
  • 28
  • 29
  • 1
    How do I generate a good degree of randomness? I ran the above code in a loop and I used a TreeSet to detect dupes, I start getting duplicates by 173170th iteration of the loop, sometimes earlier. – Farhad Sep 15 '16 at 13:54
4

I don't know why noone realized that but I think the point is to generate "unique" random number which I am also trying to do that. I managed to generate 11 digits random number but I am not sure how to generate unique numbers. Also my approach is a little different. In this method I am appending number chars next to each other with for loop. Then returning long number.

public long generateID() { 
    Random rnd = new Random();
    char [] digits = new char[11];
    digits[0] = (char) (rnd.nextInt(9) + '1');
    for(int i=1; i<digits.length; i++) {
        digits[i] = (char) (rnd.nextInt(10) + '0');
    }
    return Long.parseLong(new String(digits));
}
rawsly
  • 372
  • 1
  • 5
  • 20
1

I would use

long theRandomNum = (long) (Math.random()*Math.pow(10,10));
scylla
  • 124
  • 9
1

A general solution to return a 'n' digit number is

Math.floor(Math.random() * (9*Math.pow(10,n-1))) + Math.pow(10,(n-1))

For n=3, This would return numbers from 100 to 999 and so on.

You can even control the end range, i.e from 100 to 5xx but setting the "9" in the above equation "5" or any other number from 1-9

Amol Pednekar
  • 127
  • 1
  • 8
0

This is a utility method for generating a fixed length random number.

    public final static String createRandomNumber(long len) {
    if (len > 18)
        throw new IllegalStateException("To many digits");
    long tLen = (long) Math.pow(10, len - 1) * 9;

    long number = (long) (Math.random() * tLen) + (long) Math.pow(10, len - 1) * 1;

    String tVal = number + "";
    if (tVal.length() != len) {
        throw new IllegalStateException("The random number '" + tVal + "' is not '" + len + "' digits");
    }
    return tVal;
}
Robert Höglund
  • 954
  • 9
  • 12
0

You can use SecureRandom class to generate random long number. I always use java.security.SecureRandom in any security decisions and generatin security code like OTP. It make cryptographically strong random values by using a cryptographically strong pseudo-random number generator. Using java.security.SecureRandom make ensure that generated number is unique and secure.

 public static long generate() {
    try {
        SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
        long l = secureRandom.nextLong(System.currentTimeMillis());
        return 1000000000 + l;
    } catch (NoSuchAlgorithmException e) {
        throw new RuntimeException(e);
    }
}
-1

Maybe you are looking for this one:

Random rand = new Random();

long drand = (long)(rand.nextDouble()*10000000000L);

You can simply put this inside a loop.

emiljho
  • 572
  • 1
  • 10
  • 18
-2

Hi you can use the following method to generate 10 digit random number

private static int getRndNumber() {
    Random random=new Random();
    int randomNumber=0;
    boolean loop=true;
    while(loop) {
        randomNumber=random.nextInt();
        if(Integer.toString(randomNumber).length()==10 && !Integer.toString(randomNumber).startsWith("-")) {
            loop=false;
        }
        }
    return randomNumber;
}
Ganesa Vijayakumar
  • 2,422
  • 5
  • 28
  • 41
  • Need to use `long` (not `int`) due to overflow - see accepted answer for this question. Other than that, it's a bad idea to use a loop to reach a number with a certain number of decimals - it gives a runtime penalty in the average case. – poplitea Sep 29 '12 at 11:48
-2

this is for random number starting from 1 and 2 (10 digits).

public int gen() {
    Random r = new Random(System.currentTimeMillis());
    return 1000000000 + r.nextInt(2000000000);
}

hopefully it works.

Reza Rachman
  • 143
  • 3
  • 15
  • seed should be used very carefully. if this function is invoked parallelly in same millisecond, then it will generate same value. – khanmizan Aug 26 '18 at 06:57