如何使用C中的rand()函数生成16位随机数



我正试图在一个银行账户创建示例的函数中生成一个16位随机卡号。我尝试了下面的代码,但没有成功。

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);
}

你能帮我吗?

您的程序有几个不同的问题:

  1. 最引人注目的是这条线:

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

    它并不像你想象的那样。^运算符执行两个操作数的逐位异或,它不计算幂。

  2. 您使用循环将0从数字中排除,这是不必要的(可以在没有循环的情况下完成(,而且似乎也是错误的,因为0是一个完全有效的数字。如果你想强制你的数字有16位,那么你只希望最有效的一位不同于0,而不是所有。

  3. 循环从i=0运行到14,因此生成的是15位数字,而不是16位。

  4. 每次调用此函数时,都会调用srand(time(0))。如果在同一秒内调用,这将使函数生成相同的数字(time(0)以秒为单位返回当前时间戳(。您可能不希望这样,并且应该在main()中只调用srand()一次

  5. 没有理由对您的号码进行签名,这只会导致潜在的问题,请使用unsigned

这里有一个相当简单的代码版本,可以实现您想要的。如果你正在寻找一个更快/更优化的版本,你可能想通过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);
}

您的代码中存在以下几个问题:

  • srand(time(0));用于对伪随机数生成器进行种子。在main()函数中只使用一次,否则在同一秒内生成的所有数字都将相同
  • 要生成一个16位的随机数,唯一不能为零的数字是第一个,其他所有数字都可以为零,这与代码不同
  • 10^i不计算C中10的第i次幂,它评估10i
  • 你没有计算出足够的数字
  • randd未定义

计算从最高有效位到最低有效位的数字更容易。这是一个修改版本:

#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: %lldn", cardnumber);
}

由于RAND_MAX保证大于10000,因此一次可以计算4位数字:

#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: %lldn", cardnumber);
}

在大多数平台上,RAND_MAX要大得多,所以这里有一个替代方案可以利用这一点,并使用更少的调用来生成号码:

#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: %lldn", cardnumber);
}

但是请注意,卡号有额外的限制,例如限制值范围,并且必须有有效的Luhn校验和。

正如评论中所指出的,如果你不必对卡号进行任何算术运算,如加法、减法等。最好将卡号存储为字符串:

int getRandomDigit() {
return rand() % 10;
}
void generateCardNumber(char cardNumber[], int size) {
for (int i = 0; i < size; i++) {
cardNumber[i] = '0' + getRandomDigit();
}
cardNumber[size] = '';
}
int main() {
srand(time(NULL));
const int size = 16;
char card1[size + 1], card2[size + 1];
generateCardNumber(card1, size);
generateCardNumber(card2, size);
printf("%sn", card1);
printf("%sn", card2);
}

上面的代码生成一个16位的卡片数字,如下所示:

0216624478324435
8815844216687237

最新更新