简体   繁体   中英

How to generate 12 digit random number in C?

I'm trying to generate 12 digit random numbers in C, but it's always generating 10 digit numbers.

#include <stdio.h>
#include <time.h>
#include <stdlib.h>

void main()
{
   srand(time(NULL));
   long r = rand();
   r = r*100;
   printf("%ld",r);
}

rand() returns an int value in the range of [0...RAND_MAX]

Based on the C spec, RAND_MAX >= 32767 and RAND_MAX <= INT_MAX .

Call rand() multiple times to create a wide value


unsigned long long rand_atleast12digit(void) {
  unsigned long long r = rand();
  #if RAND_MAX >= 999999999999
  #elif RAND_MAX >= 999999
    r *= RAND_MAX + 1ull;
    r += rand();
  #else
    r *= RAND_MAX + 1ull;
    r += rand();
    r *= RAND_MAX + 1ull;
    r += rand();
  #endif
  return r;
}

The above returns a number if the range of 0 to at least 999,999,999,999. To reduce that to only that range, code could use return r % 1000000000000; .


Using % likely does not create an balanced distribution of random numbers. Other posts address details of how to cope with that like this good one incorporated as follows.

#if RAND_MAX >= 999999999999
  #define R12DIGIT_DIVISOR (RAND_MAX/1000000000000)
#elif RAND_MAX >= 999999
  #define RAND_MAX_P1  (RAND_MAX+1LLU)
  #define R12DIGIT_DIVISOR ((RAND_MAX_P1*RAND_MAX_P1-1)/1000000000000)
#else
  #define RAND_MAX_P1  (RAND_MAX+1LLU)
  #define R12DIGIT_DIVISOR  ((RAND_MAX_P1*RAND_MAX_P1*RAND_MAX_P1-1)/1000000000000)
#endif

unsigned long long rand_12digit(void) {
    unsigned long long retval;
    do { 
        retval = rand_atleast12digit() / R12DIGIT_DIVISOR;
    } while (retval == 1000000000000);
    return retval;
}

Note that the quality of rand() is not well defined, so repeated calls may not provide high quality results.


OP's code fails if long is 32-bit as it lacks range for a 12 decimal digit values. @Michael Walz

If long is wide enough, *100 will always make the least 2 decimal digits 00 - not very random. @Alexei Levenkov

long r = rand();
r = r*100;

The result of rand is int , which means you can't get a 12 digit number directly from it.

If you need value that is always 12 digits you need to make sure values fit in particular range.

Sample below assumes that you need just some of the numbers to be 12 digits - you just need 8 extra bits - so shifting and OR'ing results would produce number in 0x7fffffffff-0 range that would often result up to 12 digit output when printed as decimal:

r = rand();
r = (r << 8) | rand();

PS: Make sure the variable that will store the result is big enough to store the 12 digit number.

My simple way to generate random strings or numbers is:

static char *ws_generate_token(size_t length) {

    static char charset[] = "abcdefghijklmnopqrstuvwxyz1234567890";
    char *randomString = NULL;

    if (length) {
        randomString = malloc(sizeof(char) * (length + 1));

        if (randomString) {
            for (int n = 0; n < length; n++) {
                int key = rand() % (int)(sizeof(charset) -1);
                randomString[n] = charset[key];
            }

            randomString[length] = '\0';
        }
    }

    return randomString;
}

Explain the code

  1. Create an array of chars which will contains (numbers, alphabets...etc)
  2. Generate a random number between [0, array length], let's name it X.
  3. Get the character at random X position in the array of chars.
  4. finally, add this character to the sequence of strings (or numbers) you want to have in return.

How to use it?

#define TOKEN_LENGTH      12
char *token;

token = ws_generate_token(TOKEN_LENGTH);

conversion from string to int

int token_int = atol(token);

dont forget !

free(token); // free the memory when you finish
    #include <stdio.h>
#include <stdlib.h>

int main()
{
   int i, n;
   time_t t;

   n = 5;

   /* Intializes random number generator int range */
   srand((unsigned) time(&t));

   /* Print 5 random numbers from 50 to back
   for( i = 0 ; i < n ; i++ ) 
   {
      printf("%d\n", rand() % 50);
   }

   return(0);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM