C语言函数-rand函数,一个生成伪随机数的函数

目录

`rand()` 函数生成的随机数序列是伪随机的。

rand函数的种子

有没有什么方法生成真正的随机数?

在C语言中:

那验证码的原理是什么?

在C语言中,`rand()` 函数是一个常用的库函数,它用来生成伪随机数。这个函数定义在C标准库的 `` 头文件中。`rand()` 函数返回一个介于0到RAND_MAX之间的整数,RAND_MAX是一个常量,表示`rand()`函数能生成的最大随机数,它的值至少为32767。

如果你直接用rand函数打印,不管尝试多少次,结果都是一样的。


`rand()` 函数生成的随机数序列是伪随机的。

因为它们是通过一个已知算法生成的,这个算法在初始时需要一个种子值来初始化。如果没有设置种子,默认的种子是1。这意味着,如果你不设置种子,每次程序运行时生成的随机数序列都是相同的。


为了生成不同的随机数序列,通常使用 `srand()` 函数来设置随机数生成的种子。`srand()` 函数也定义在 `` 头文件中。它需要一个无符号整数作为种子值。通常,我们会使用当前时间来作为种子值,因为时间在不断变化,所以每次运行程序时种子值都不同,从而生成不同的随机数序列。
下面是一个使用 `rand()` 和 `srand()` 函数的简单示例:

#include 
#include 
#include 

int main() {
    // 使用当前时间作为种子值
    srand((unsigned int)time(NULL));

    // 生成并打印10个随机数
    for(int i = 0; i < 10; i++) {
        printf("%d ", rand());
    }

    return 0;
}


在这个例子中,我们首先包含了必要的头文件,然后使用 `time(NULL)` 获取当前时间,并将它作为种子传递给 `srand()` 函数。之后,在循环中使用 `rand()` 函数生成10个随机数并打印它们。

rand函数的种子

在程序中我们一般是使用程序运行的时间作为种子的,因为时间时刻在发生变化的。在C语言中有一个函数叫 time ,就可以获得这个时间,time函数原型如下:​

time_t time (time_t* timer);

time 函数会返回当前的日历时间,其实返回的是1970年1月1日0时0分0秒到现在程序运行时间之间的差值,单位是秒。返回的类型是time_t类型的,time_t 类型本质上其实就是32位或者64位的整型类型。time函数的参数 timer 如果是非NULL的指针的话,函数也会将这个返回的差值放在timer指向的内存中带回去。如果 timer 是NULL,就只返回这个时间的差值。time函数返回的这个时间差也被叫做:时间戳。​time函数的时候需要包含头文件:time.h

#include 
#include 
#include 
int main(){
 //使用time函数的返回值设置种子
​ //因为srand的参数是unsigned int类型,我们将time函数的返回值强制类型转换
​    srand((unsigned int)time(NULL)); 
    printf("%d\n", rand()); 
    printf("%d\n", rand()); 
    printf("%d\n", rand());
    printf("%d\n", rand()); 
    printf("%d\n", rand()); 
return 0;
}

设置随机数的范围

​如果我们要生成0~99之间的随机数,方法如下

rand() % 100;

//余数的范围是0~99​

如果要生成1~100之间的随机数,方法如下:

rand()%100+1;

//%100的余数是0~99,0~99的数字+1,范围是1~100​

如果要生成100~200的随机数,方法如下:

​100 + rand()%(200-100+1)

//余数的范围是0~100,加100后就是100~200

有没有什么方法生成真正的随机数?

或者是更随机的随机数呢?

在计算机科学中,生成真正的随机数是一个挑战,因为计算机是确定性的机器。不过目前也有几种方法可以用来生成接近真正随机数的值:
硬件随机数生成器(HRNG):这些设备利用物理现象,如电子噪声、放射性衰变、量子现象等,来生成随机数。这些设备通常能够提供非常高的随机性,但成本也相对较高。
操作系统提供的随机数生成器:一些操作系统提供了更安全的随机数生成器,如Linux的/dev/random和/dev/urandom。这些设备驱动程序通常会收集各种系统熵(如键盘击键、鼠标移动、磁盘访问时间等)来生成随机数。
混合方法:可以结合使用伪随机数生成器(PRNG)和硬件生成的随机数。例如,可以使用硬件随机数生成器生成的种子来初始化伪随机数生成器,从而获得一个结合了真随机性和伪随机数生成效率的解决方案。
网络源:一些在线服务提供真正的随机数,这些服务可能会基于天气数据、股票市场波动、用户行为等来生成随机数。

在C语言中:

如果你需要更高质量的随机数,可以使用一些专门的库,比如:
ISO C11 : 从C11开始,C语言标准库中引入了原子操作的函数,其中包括stdatomic.h头文件中的random()函数,这是一个基于硬件的随机数生成器。
OpenSSL: OpenSSL是一个广泛使用的开源加密库,它提供了强大的伪随机数生成器(PRNG),如RAND_bytes()函数,它可以生成适合加密用途的随机数。
GNU Scientific Library (GSL): GSL是一个为科学计算提供的开源库,它包含了多种随机数生成器,如MT19937(Mersenne Twister)算法,这是一个非常高质量的伪随机数生成器。
Intel’s Integrated Performance Primitives (IPP): IPP是Intel提供的一组函数库,用于优化性能密集型应用程序,它也包含了一些随机数生成的函数。
Windows CryptoAPI: 在Windows操作系统中,可以使用CryptoAPI中的CryptGenRandom函数来生成高质量的随机数。
/dev/random 和 /dev/urandom: 在类Unix系统中,这两个特殊文件提供了访问系统熵池的方式,可以用来生成高质量的随机数。

在生活中,最容易联想到的随机数就是验证码了。

那验证码的原理是什么?


### 验证码
验证码(CAPTCHA)的设计目标是确保只有真实用户能够通过验证,同时防止自动化的机器人或爬虫程序。为了达到这个目标,验证码通常采用以下技术和方法来保障其随机性:
1. **随机字符生成**:验证码通常由一组随机选择的字母和数字组成。这些字符的选取通常依赖于安全的随机数生成器,以确保每次生成的验证码都是独一无二的。
2. **字符混淆**:为了增加自动识别的难度,验证码可能会采用字符混淆技术,如改变字符的大小、形状、颜色或加入背景干扰。这种混淆也是随机进行的,使得每个验证码都有所不同。
3. **背景干扰**:验证码的背景可能会加入随机的线条、点或其他形状,以干扰自动识别程序。这些干扰元素的位置、颜色和形状都是随机生成的。
4. **动态生成**:验证码通常是在用户请求时动态生成的,这意味着每次刷新页面或请求验证码时,都会得到一个全新的随机验证码。
5. **时间限制和一次性使用**:为了防止重放攻击,验证码通常有时间限制,超时后需要重新生成。此外,一旦验证码被使用或验证失败,它通常会被废弃,确保每个验证码只使用一次。
6. **安全性考虑**:验证码生成算法需要考虑安全性,防止被自动化工具破解。这可能包括使用复杂的字符混淆技术、限制连续字符的使用、确保字符之间没有明显的模式等。
### 二维码
二维码是一种可以存储大量信息的图形表示形式,它们通常用于快速数据访问,如网址、联系方式等。为了保障二维码的随机性,通常采用以下技术和方法:
1. **数据编码**:二维码的数据编码过程中会使用纠错码,这可以确保即使二维码损坏或部分无法识别,也能正确解码。纠错码的生成通常涉及随机算法。
2. **布局和设计**:二维码的布局和设计可能包含随机元素,如二维码中的空白区域、图标的位置和大小等。这些随机元素可以增加二维码的复杂度和安全性。
3. **动态生成**:与验证码类似,二维码通常也是动态生成的,确保每次生成的二维码都是独一无二的。
4. **时间戳和有效期**:为了增加安全性,一些二维码可能包含时间戳或有效期,这意味着它们只能在特定时间范围内使用。
总的来说,验证码和二维码的随机性保障是通过多种技术和方法来实现的,以确保其安全性和可靠性。这些技术和方法包括随机数生成、字符混淆、背景干扰、动态生成、时间限制和安全性考虑等。

(以上内容来源于AI)

你可能感兴趣的:(C语言学习专栏,c语言,开发语言)