简体   繁体   中英

How can I generate a 16 digit random number with rand() function in C?

I'm trying to generate a 16 digit random card number in a function for a bank account creating sample. I tried the code below, but it didn't work.

void generate_card_number() {
    srand(time(0));
    long long int cardnumber = 0;
    int i, randctrl;

    for (i = 0; i < 15; i++) {
        do {
            randctrl = rand() % 9;
        } while (randctrl == 0);
        cardnumber += ((10^i) * randctrl);
    }
    printf("\nThe Card Number : %lld", cardnumber);
}

Could you help me, please?

There are several different issues with your program:

  1. The most noticeable is this line:

     cardnumber+= ( (10^i) * randd );

    which does not do what you think it does. The ^ operator performs the bitwise XOR of the two operands, it does not compute a power.

  2. You are excluding 0 from your digits with a loop, that's unneeded (can be done without a loop) and also seems wrong, since 0 is a perfectly valid digit. If you want to force your number to have 16 digits then you only want the most significant one to be different than 0 , not all of them.

  3. Your loop runs for i=0 to 14 , so you are generating 15 digits, not 16.

  4. You are calling srand(time(0)) every time you call this function. This will make the function generate the same number if called within the same second ( time(0) returns the current timestamp in seconds). You probably do not want this, and should call srand() only once in your main() .

  5. There is no reason for your numbers to be signed, this can only cause potential problems, use unsigned .

Here's a reasonably simple version of the code which achieves what you want. If you are looking for a faster / more optimized version you might want to check out this other answer by chqrlie .

void generate_card_number()
{
    unsigned long long cardnumber;
    unsigned i;

    // Ensure most significant digit is not 0
    cardnumber = rand() % 9 + 1;

    // Add 15 more digits (which can also be 0)
    for (i = 0; i < 15; i++)
    {
        cardnumber *= 10;
        cardnumber += rand() % 10;
    }

    printf("\nThe Card Number : %llu", cardnumber);
}

There are several problems in your code:

  • srand(time(0)); is used to seed the pseudo-random number generator. Use it just once in the main() function otherwise all numbers generated during the same second will be identical.
  • To generate a 16 digit random number, the only digit that cannot be zero is the first one, all others can be, unlike what your code does.
  • 10^i does not compute the i-th power of 10 in C, it evaluates 10 xor i .
  • you do not compute enough digits.
  • randd is undefined.

It is easier to compute the digits from the most significant to the least significant. Here is a modified version:

#include <stdlib.h>

void generate_card_number() {
    // start with a digit between 1 and 9
    long long cardnumber = 1 + rand() % 9;
    // add the remaining 15 digits
    for (int i = 1; i < 16; i++)
        cardnumber = cardnumber * 10 + rand() % 10;
    printf("The Card Number: %lld\n", cardnumber);
}

Since RAND_MAX is guaranteed to be larger than 10000 , you can compute 4 digits at a time:

#include <stdlib.h>

void generate_card_number() {
    // start with a number between 1000 and 9999
    long long cardnumber = 1000 + rand() % 9000;
    cardnumber = cardnumber * 10000 + rand() % 10000; // add 4 digits
    cardnumber = cardnumber * 10000 + rand() % 10000; // add 4 digits
    cardnumber = cardnumber * 10000 + rand() % 10000; // add the last 4 digits
    printf("The Card Number: %lld\n", cardnumber);
}

On most platforms, RAND_MAX is much larger, so here is alternative to take advantage of this and use fewer calls to generate the number:

#include <stdlib.h>

void generate_card_number() {
#if RAND_MAX >= 100000000
    // start with a number between 10000000 and 99999999
    long long cardnumber = 10000000 + rand() % 90000000;
    cardnumber = cardnumber * 100000000 + rand() % 100000000; // add 8 digits
#else
    // start with a number between 1000 and 9999
    long long cardnumber = 1000 + rand() % 9000;
    cardnumber = cardnumber * 10000 + rand() % 10000; // add 4 digits
    cardnumber = cardnumber * 10000 + rand() % 10000; // add 4 digits
    cardnumber = cardnumber * 10000 + rand() % 10000; // add the last 4 digits
#endif
    printf("The Card Number: %lld\n", cardnumber);
}

Note however that card numbers have extra contraints, such as restricted value ranges and must have a valid Luhn checksum.

As pointed out in comments, if you don't have to do any arithmetic operations with card numbers like addition, subtraction etc. It might be a better idea to store card number as a string instead:

int getRandomDigit() {
    return rand() % 10;
}

void generateCardNumber(char cardNumber[], int size) {
    for (int i = 0; i < size; i++) {
        cardNumber[i] = '0' + getRandomDigit();
    }
    cardNumber[size] = '\0';
}

int main() {
    srand(time(NULL));
    const int size = 16;
    char card1[size + 1], card2[size + 1];

    generateCardNumber(card1, size);
    generateCardNumber(card2, size);

    printf("%s\n", card1);
    printf("%s\n", card2);
}

Above code generates a 16 digit card digit as follows:

0216624478324435
8815844216687237

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