本文目录
- 生成随机数的概念
- 相关函数介绍
- time()函数
- srand()函数
- srandom()函数
- random函数()
- getpid()函数
- 生成随机数的方法
- 例子1:使用rand()函数生成随机数
- 例子2:使用random函数生成随机数
- 例子3:使用getpid函数生成随机数
- 例子4:使用/dev/random和/dev/urandom设备文件生成随机数
生成随机数的概念
生成随机数是指按照一定的规律,产生一些看似无规律的数字序列。在计算机中,通常使用随机数生成器来生成随机数。随机数生成器可以分为真随机数生成器和伪随机数生成器两种。真随机数生成器是利用物理现象产生的随机事件(如放射性衰变)来生成随机数。而伪随机数生成器是利用算法产生的数字序列,虽然看似无规律,但实际上是可以预测的。
在计算机中,通常使用伪随机数生成器来生成随机数。伪随机数生成器通常由一个种子值和一个算法组成。种子值是生成随机数的起始值,而算法则是根据种子值和一些数学运算来产生下一个随机数。为了让生成的随机数更加随机,通常会将种子值设置为当前的时间戳,以确保每次运行程序时生成的随机数都不同。
相关函数介绍
由于在生成随机数的时候会使用到某些函数,接下来先进行补充。
time()函数
C语言的time()函数原型为:
time_t time(time_t *t);
其中,time_t是C语言标准库中的一种时间类型,time()函数的返回值类型为time_t。该函数的作用是获取当前时间的秒数,并将其返回。如果将一个time_t类型的指针传递给该函数,它会将当前时间的秒数存储在该指针所指向的变量中。
以下是一个简单的示例:
#include #include int main(int argc, char const *argv[]){time_t time_value;time_value = time(NULL);printf("time_value:%ld\n", time_value);return 0;}
在Linux中的运行结果为:
该程序输出的是当前时间的秒数。如果想要将时间戳转换为其他形式的时间表示,可以使用C语言标准库中的其他函数,例如gmtime()、localtime()等。
time(NULL)
函数获取的是从1970年1月1日0时0分0秒开始到当前时刻的秒数,即Unix时间戳。Unix时间戳是计算机领域中常用的时间表示方法之一,它是以UTC时间为基准,以秒为单位计算的时间戳,可以方便地进行时间计算和比较。
需要注意的是,由于time(NULL)获取的是当前时刻的秒数,因此它的返回值是一个动态变化的值,每次调用都会返回不同的值。如果需要在程序中多次使用当前时间,应该将time(NULL)的返回值保存在一个变量中,而不是多次调用该函数。
srand()函数
srand()函数是C语言标准库中的一个函数,用于设置随机数生成器的种子。它的原型如下:
void srand(unsigned int seed);
其中,seed是一个无符号整数,用于指定随机数生成器的种子。调用srand()函数后,随机数生成器将以seed作为起始值,生成一系列随机数。
需要注意的是,如果不调用srand()函数,随机数生成器将使用一个默认的种子。由于默认种子通常是根据系统时间来生成的,因此每次运行程序时,随机数生成器都会生成不同的随机数序列。
以下是一个简单的示例:
#include #include #include int main(int argc, char const *argv[]){int r;// 设置随机数的种子srand(time(NULL));for (int i = 0; i < 5; i++){// 生成随机数r = rand();printf("%d\n", r);}return 0;}
在Linux中得到的运行结果为:
该程序使用time()函数获取当前时间的秒数作为种子,调用srand()函数设置随机数生成器的种子,然后调用rand()函数生成一系列随机数。由于种子是基于时间的,因此每次运行程序时,生成的随机数序列都是不同的。
srandom()函数
srandom()
函数是C语言中用于初始化随机数生成器的函数。它的作用是设置一个种子,使得随机数生成器能够产生不同的随机数序列。它的原型如下:
void srandom(unsigned int seed);
srandom()
函数需要一个unsigned int
类型的参数作为种子,这个种子可以是任意值,但是推荐使用当前时间作为种子,以保证每次程序运行时生成的随机数序列不同。使用srandom()
函数之后,每次调用random()
函数都会生成一个新的随机数,而且这些随机数之间也没有任何关联,也不会重复。
下面是一个示例程序,演示如何使用srandom()
函数和random()
函数生成随机数:
#include #include #include int main(int argc, char const *argv[]){int i, r;unsigned int seed;srandom(seed);for (int i = 0; i < 5; i++){r = random();printf("%d\t", r);}printf("\n");return 0;}
在Linux中观察到的运行结果:
在这个示例程序中使用time()
函数获取当前时间,将其转换为unsigned int
类型的值,并作为srandom()
函数的参数,以此来初始化随机数生成器。然后使用random()
函数生成5个随机数,并将其输出到屏幕上。由于使用了srandom()
函数,每次运行程序时,生成的随机数序列都是不同的。
需要注意的是,在使用srandom()
函数之前,必须包含头文件,否则编译器会报错。
在上文中使用了两个函数对随机数的种子进行设定,但它们有何区别呢?
srandom()
函数和srand()
函数都是C语言中用于生成随机数的函数,它们的作用是设置随机数生成器的种子,以便产生不同的随机数序列。它们的不同之处在于参数类型和取值范围。
srand()
函数的原型如下:
void srand(unsigned int seed);
srand()
函数需要一个unsigned int
类型的参数作为种子,这个种子可以是任意值,但是推荐使用当前时间作为种子,以保证每次程序运行时生成的随机数序列不同。在使用srand()
函数之后,每次调用rand()
函数都会生成一个新的随机数,而且这些随机数之间也没有任何关联,也不会重复。注意,srand()
函数的参数是一个32位无符号整数,其取值范围是0到4294967295。
srandom()
函数的原型如下:
void srandom(unsigned int seed);
srandom()
函数也需要一个unsigned int
类型的参数作为种子,但是和srand()
函数不同的是,srandom()
函数使用的是一个48位整数作为种子,其取值范围更加广泛,可以达到更高的随机性。在使用srandom()
函数之后,每次调用random()
函数都会生成一个新的随机数,而且这些随机数之间也没有任何关联,也不会重复。注意,srandom()
函数的参数是一个32位无符号整数,但是内部会将其扩展为48位整数。
需要注意的是,srand()
函数和srandom()
函数是不可互换的,也就是说,如果在程序中使用了srandom()
函数设置了随机数生成器的种子,那么在生成随机数时必须使用random()
函数。同样地,如果在程序中使用了srand()
函数设置了随机数生成器的种子,那么在生成随机数时必须使用rand()
函数。
random函数()
random()
函数是C语言标准库中用于生成随机数的函数。它的函数原型定义在头文件中:
long int random(void);
该函数返回一个长整型数值,取值范围在0到RAND_MAX
之间(包含0和RAND_MAX
)。RAND_MAX
是一个常量,它表示随机数的最大值,其值至少为32767。
在调用random()
函数之前,需要先使用srandom()
函数来设置随机数种子。如果没有调用srandom()
函数,那么random()
函数每次都会使用默认的随机数种子,生成的随机数序列就会相同。
random()
函数的实现使用了一个名为__random_data
的结构体来存储随机数生成器的状态。这个结构体包括了一些用于生成随机数的参数,比如随机数种子、随机数生成器的状态等等。在random()
函数中,首先调用__random_getstate()
函数获取随机数生成器的状态,然后再调用__random_r()
函数生成一个随机数,并返回该随机数。
需要注意的是,random()
函数不是真正的随机数生成器,它只是生成一个伪随机数。生成的随机数是依据随机数生成器的状态(种子)和算法计算得到的,因此在给定相同的种子和算法的情况下,random()
函数生成的随机数序列是固定的。如果需要更高质量的随机数,可以使用其他的随机数生成器库,例如OpenSSL、libgcrypt等。
getpid()函数
getpid()
函数是一个用于获取当前进程ID(Process ID)的函数,它的函数原型定义在头文件中:
#include #include pid_t getpid(void);
该函数返回一个pid_t
类型的值,表示当前进程的ID。进程ID是一个非负整数,通常由操作系统分配。每个进程都有一个唯一的进程ID,可以用来标识进程。
需要注意的是,进程ID并不是随机分配的,而是按照一定的规则分配的。通常情况下,进程ID是连续的,即相邻的进程ID之间只相差1。但是,如果某个进程退出,它的进程ID可能会被其他进程重新使用,因此不能保证进程ID是连续的。
下面是一个使用getpid()
函数获取当前进程ID的例子:
#include #include #include int main(int argc, char const *argv[]){pid_t pid = getpid();printf("pid的值为:%d\n", pid);return 0;}
在Linux中观察到的运行结果为:
生成随机数的方法
下面是4个例子演示了不同的生成随机数的方法。
例子1:使用rand()函数生成随机数
#include #include #include int main(int argc, char const *argv[]){srand(time(NULL));int random_number = rand() % 10;printf("得到的随机数为:%d\n", random_number);return 0;}
在Linux中的运行结果为:
例子2:使用random函数生成随机数
#include #include #include int main(int argc, char const *argv[]){// 初始化随机数种子srandom(time(NULL));// 生成0~9之间的随机数int random_num = random() % 10;printf("随机数为:%d\n", random_num);return 0;}
在Linux中的运行结果为:
例子3:使用getpid函数生成随机数
#include #include #include int main(int argc, char const *argv[]){srand(getpid());printf("随机数为:%d\n", rand() % 10);return 0;}
在Linux中观察到的运行结果为:
例子4:使用/dev/random和/dev/urandom设备文件生成随机数
#include #include #include #include int main(int argc, char const *argv[]){int random_num;// 从/dev/random设备文件中读取随机数int fd = open("/dev/random", O_RDONLY);if (fd < 0){perror("open /dev/random failed");return -1;}read(fd, &random_num, sizeof(random_num));close(fd);printf("/dev/random生成的随机数为:%d\n", random_num);// 从/dev/urandom设备文件中读取随机数fd = open("/dev/urandom", O_RDONLY);if (fd < 0){perror("open /dev/urandom failed");return -1;}read(fd, &random_num, sizeof(random_num));close(fd);printf("/dev/urandom生成的随机数为:%d\n", random_num);return 0;}
在Linux中观察到的运行结果:
这些例子展示了不同的生成随机数的方法,包括使用rand函数、random函数、getpid函数以及/dev/random和/dev/urandom设备文件。在实际开发中,可以根据具体需求选择适合的随机数生成方法。