C语言中生成随机数的方法

生成随机数的概念

  生成随机数是指按照一定的规律,产生一些看似无规律的数字序列。在计算机中,通常使用随机数生成器来生成随机数。随机数生成器可以分为真随机数生成器和伪随机数生成器两种。真随机数生成器是利用物理现象产生的随机事件(如放射性衰变)来生成随机数。而伪随机数生成器是利用算法产生的数字序列,虽然看似无规律,但实际上是可以预测的。

  在计算机中,通常使用伪随机数生成器来生成随机数。伪随机数生成器通常由一个种子值和一个算法组成。种子值是生成随机数的起始值,而算法则是根据种子值和一些数学运算来产生下一个随机数。为了让生成的随机数更加随机,通常会将种子值设置为当前的时间戳,以确保每次运行程序时生成的随机数都不同。

相关函数介绍

  由于在生成随机数的时候会使用到某些函数,接下来先进行补充。

time()函数

  C语言的time()函数原型为:

time_t time(time_t *t);

  其中,time_t是C语言标准库中的一种时间类型,time()函数的返回值类型为time_t。该函数的作用是获取当前时间的秒数,并将其返回。如果将一个time_t类型的指针传递给该函数,它会将当前时间的秒数存储在该指针所指向的变量中。

  以下是一个简单的示例:

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

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 <stdio.h>
#include <time.h>
#include <stdlib.h>

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 <stdio.h>
#include <stdlib.h>
#include <time.h>

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()函数之前,必须包含头文件<time.h>,否则编译器会报错。

  在上文中使用了两个函数对随机数的种子进行设定,但它们有何区别呢?

  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语言标准库中用于生成随机数的函数。它的函数原型定义在<stdlib.h>头文件中:

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)的函数,它的函数原型定义在<sys/types.h>头文件中:

#include <sys/types.h>
#include <unistd.h>
pid_t getpid(void);

  该函数返回一个pid_t类型的值,表示当前进程的ID。进程ID是一个非负整数,通常由操作系统分配。每个进程都有一个唯一的进程ID,可以用来标识进程。

  需要注意的是,进程ID并不是随机分配的,而是按照一定的规则分配的。通常情况下,进程ID是连续的,即相邻的进程ID之间只相差1。但是,如果某个进程退出,它的进程ID可能会被其他进程重新使用,因此不能保证进程ID是连续的。

  下面是一个使用getpid()函数获取当前进程ID的例子:

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

int main(int argc, char const *argv[])
{
    pid_t pid = getpid();

    printf("pid的值为:%d\n", pid);
    return 0;
}

在Linux中观察到的运行结果为:
在这里插入图片描述

生成随机数的方法

  下面是4个例子演示了不同的生成随机数的方法。

例子1:使用rand()函数生成随机数

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

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 <stdio.h>
#include <stdlib.h>
#include <time.h>

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 <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char const *argv[])
{
    srand(getpid());
    printf("随机数为:%d\n", rand() % 10);
    return 0;
}

在Linux中观察到的运行结果为:
在这里插入图片描述

例子4:使用/dev/random和/dev/urandom设备文件生成随机数

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>

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设备文件。在实际开发中,可以根据具体需求选择适合的随机数生成方法。

  • 22
    点赞
  • 123
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值