程序生成随机数

随机数

  • [1. Qt](#1. Qt)
    • [1.1 qsrand() 和qrand()](#1.1 qsrand() 和qrand())
    • [1.2 QRandomGenerator 类](#1.2 QRandomGenerator 类)
  • [2. C语言](#2. C语言)
    • [2.1 使用 rand() 和 srand() 函数](#2.1 使用 rand() 和 srand() 函数)
    • [2.2 使用 <random.h> 库(C11 标准)](#2.2 使用 <random.h> 库(C11 标准))
  • [3. C++](#3. C++)
    • [3.1 使用 <cstdlib> 和 <ctime> 库(旧方法)](#3.1 使用 库(旧方法))
    • [3.2 使用 <random> 库(C++11 及以后推荐方法)](#3.2 使用 库(C++11 及以后推荐方法))
    • [3.3 生成浮点数随机数](#3.3 生成浮点数随机数)

1. Qt

1.1 qsrand() 和qrand()

通过qsrand() 和qrand()函数来生成随机数。随机数生成器本质上是按照特定算法生成一系列看似随机的数字。但实际上,这些数字是基于一个初始值(即种子)按照固定算法计算得出的。如果每次使用相同的种子,那么随机数生成器将产生相同的随机数序列。qsrand() 函数的作用就是为随机数生成器设置这个初始种子,从而影响后续生成的随机数序列。

  1. qsrand() 是 Qt 框架提供的一个用于初始化随机数生成器种子的函数,它在<QtCore/QRandomGenerator> (旧版本中是 <QtCore/QTime> 配合使用)相关的随机数生成操作中扮演着重要角色。
    该函数在 <QtCore/QRandomGenerator> 头文件(在旧版本中为 <QtCore/QCoreApplication> )中声明。这里的参数 seed 是一个无符号整数,作为随机数生成器的种子。
cpp 复制代码
void qsrand(uint seed);
  1. qrand() 函数用于生成具体的随机数。qrand() 函数用于生成伪随机整数。该函数生成的随机数范围是 0, RAND_MAX,其中 RAND_MAX 是一个常量,表示随机数的最大值。RAND_MAX 的值在不同的系统和编译器中可能会有所不同,但在大多数系统中,RAND_MAX 被定义为 32767 (即 2^15 - 1)。这意味着 qrand() 函数生成的随机数是一个非负整数,其取值范围从 0 到 RAND_MAX。
cpp 复制代码
#include <QCoreApplication>
#include <QDebug>
#include <QTime>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // 使用当前时间作为种子初始化随机数生成器
    qsrand(QTime::currentTime().msec());

    // 生成并输出10个随机整数
    for (int i = 0; i < 10; ++i) {
        int randomNumber = qrand();
        qDebug() << "生成的随机数: " << randomNumber;
    }

    return a.exec();
}

在这个例子中,使用 QTime::currentTime().msec() 作为种子,因为每毫秒的时间值通常是不同的,所以每次运行程序时,随机数生成器的种子不同,进而产生不同的随机数序列。qrand() 函数用于生成具体的随机数。

1.2 QRandomGenerator 类

不过,在现代 Qt(Qt 5.10 及以后版本)中,推荐使用 QRandomGenerator 类来生成随机数,它提供了更安全、更现代的随机数生成方式,而 qsrand() 和 qrand() 已被标记为过时。示例如下:

cpp 复制代码
#include <QCoreApplication>
#include <QDebug>
#include <QRandomGenerator>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // 生成并输出10个随机整数
    for (int i = 0; i < 10; ++i) {
        quint32 randomNumber = QRandomGenerator::global()->generate();
        qDebug() << "生成的随机数: " << randomNumber;
    }

    return a.exec();
}

在这个示例中,QRandomGenerator::global()->generate() 用于生成一个无符号 32 位整数的随机数,并且不需要手动设置种子,QRandomGenerator 会自动处理种子的初始化,提供更好的随机性和安全性。
QRandomGenerator::global()->bounded(0, 101) 用于生成一个范围在 0, 100 的随机整数

  • 可重复性问题:如果需要复现相同的随机数序列,可使用固定的种子调用 qsrand()。但在大多数实际应用场景中,为了得到不同的随机数序列,通常会使用变化的值(如当前时间)作为种子。
  • 过时性:由于 qsrand() 和 qrand() 存在一些随机性和安全性方面的问题,在新的 Qt 项目中建议使用 QRandomGenerator 类来替代。

2. C语言

2.1 使用 rand() 和 srand() 函数

  1. rand() 函数:该函数会返回一个介于 0 到 RAND_MAX 之间的伪随机整数。RAND_MAX 是一个常量,其值至少为 32767,不同系统可能会有所不同。
  2. srand() 函数:此函数用于初始化随机数生成器的种子。若每次运行程序时种子相同,rand() 函数就会生成相同的随机数序列。所以,通常会使用当前时间作为种子,以确保每次运行程序时生成不同的随机数序列。
c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main() {
    // 使用当前时间作为随机数生成器的种子
    srand(time(NULL));

    // 生成10个随机数
    for (int i = 0; i < 10; i++) {
        // 生成一个0到99之间的随机数
        int random_num = rand() % 100;
        printf("随机数 %d: %d\n", i + 1, random_num);
    }

    return 0;
}
  • srand(time(NULL)):time(NULL) 会返回当前的时间戳,将其作为 srand() 函数的参数,以此初始化随机数生成器的种子。
  • rand() % 100:rand() 函数生成一个随机整数,通过取模运算 % 100 可以将随机数的范围限制在 0 到 99 之间。

2.2 使用 <random.h> 库(C11 标准)

C11 标准引入了 <random.h> 库,该库提供了更强大、更灵活的随机数生成功能,能够生成不同分布的随机数,如均匀分布、正态分布等。

c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <random>

int main() {
    // 创建一个随机数生成器
    struct random_data rd;
    char state[32];
    initstate_r(time(NULL), state, sizeof(state), &rd);

    // 生成10个0到99之间的随机数
    for (int i = 0; i < 10; i++) {
        int random_num;
        random_r(&rd, &random_num);
        random_num = random_num % 100;
        printf("随机数 %d: %d\n", i + 1, random_num);
    }

    return 0;
}
  • initstate_r():该函数用于初始化随机数生成器的状态,使用当前时间作为种子。
  • random_r():此函数会生成一个随机整数,同样通过取模运算将随机数的范围限制在 0 到 99 之间。
  • random_data 结构体是 <random.h> 头文件里定义的,这个头文件是 C11 标准引入的,用于实现更高级的随机数生成功能。random_data 结构体用于存储随机数生成器的内部状态信息。在使用 random_r 这类可重入的随机数生成函数时,就需要借助这个结构体来保存和管理随机数生成器的状态。之所以要有这样的结构体,是因为可重入函数要能在多线程环境下安全使用,每个线程得有自己独立的随机数生成器状态,避免不同线程之间的状态相互干扰。
  • 状态数组:char state32; 定义了一个字符数组 state,用于存储随机数生成器的状态信息。
  • 在多线程环境中使用 random_r 函数时,每个线程都需要有自己独立的 random_data 结构体变量,以此保证线程安全。

3. C++

3.1 使用 和 库(旧方法)

这种方法主要利用 rand() 函数生成随机数,同时使用 srand() 函数设置随机数种子。rand() 函数会返回一个介于 0 到 RAND_MAX 之间的伪随机整数,RAND_MAX 是一个常量,其值至少为 32767。为了让每次运行程序时生成不同的随机数序列,通常会使用 srand() 结合 time() 函数以当前时间作为种子。

cpp 复制代码
#include <iostream>
#include <cstdlib>
#include <ctime>

int main() {
    // 使用当前时间作为随机数种子
    std::srand(static_cast<unsigned int>(std::time(nullptr)));

    // 生成10个0到99之间的随机数
    for (int i = 0; i < 10; ++i) {
        int randomNumber = std::rand() % 100;
        std::cout << "随机数 " << i + 1 << ": " << randomNumber << std::endl;
    }

    return 0;
}
  • std::srand(static_cast(std::time(nullptr)));:使用当前时间作为随机数种子,确保每次运行程序时生成不同的随机数序列。
  • std::rand() % 100:生成一个 0 到 99 之间的随机数。

3.2 使用 库(C++11 及以后推荐方法)

库是 C++11 引入的,提供了更强大、更灵活且随机性更好的随机数生成功能。它包含了多种随机数引擎和分布类型,可以根据需求选择合适的引擎和分布来生成随机数。

cpp 复制代码
#include <iostream>
#include <random>

int main() {
    // 定义随机数引擎,这里使用默认的随机数引擎
    std::random_device rd;
    std::mt19937 gen(rd());

    // 定义分布类型,这里使用均匀分布,范围是0到99
    std::uniform_int_distribution<> dis(0, 99);

    // 生成10个随机数
    for (int i = 0; i < 10; ++i) {
        int randomNumber = dis(gen);
        std::cout << "随机数 " << i + 1 << ": " << randomNumber << std::endl;
    }

    return 0;
}
  • std::random_device rd;:创建一个 random_device 对象,它通常用于获取真正的随机数种子。
  • std::mt19937 gen(rd());:创建一个 mt19937 随机数引擎,并使用 random_device 生成的种子进行初始化。mt19937 是一个常用的梅森旋转算法随机数引擎,具有较好的随机性和性能。
  • std::uniform_int_distribution<> dis(0, 99);:创建一个均匀整数分布对象,指定随机数的范围为 0 到 99。
  • dis(gen):通过分布对象 dis 对随机数引擎 gen 进行采样,生成一个符合指定分布的随机数。

3.3 生成浮点数随机数

使用 库也可以方便地生成浮点数随机数,以下是一个生成 0 到 1 之间浮点数随机数的示例:

cpp 复制代码
#include <iostream>
#include <random>

int main() {
    std::random_device rd;
    std::mt19937 gen(rd());
    // 定义均匀浮点分布,范围是0到1
    std::uniform_real_distribution<> dis(0.0, 1.0);

    for (int i = 0; i < 10; ++i) {
        double randomNumber = dis(gen);
        std::cout << "随机浮点数 " << i + 1 << ": " << randomNumber << std::endl;
    }

    return 0;
}

这个示例与生成整数随机数的示例类似,只是使用了 std::uniform_real_distribution 来定义浮点数的均匀分布。

相关推荐
Scott9999HH7 小时前
【IIoT流量实战】蒸汽管道阀门全关却仍有流量?用 Python 实现涡街信号 FFT 频谱分析与温压全补偿积算网关,深度拆解靠谱的涡街流量计厂家硬核技术标准
开发语言·python
码智社8 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
AI云海8 小时前
python 列表、元组、集合和字典
开发语言·python
萧瑟余晖9 小时前
JDK 26 新特性详解
java·开发语言
马优晨10 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
人邮异步社区12 小时前
怎么把C语言学到精通?
c语言·开发语言
心平气和量大福大12 小时前
C#-WPF-控件-TextBox 数据绑定
开发语言·c#·wpf
ttwuai13 小时前
Cursor 生成 CRUD 后,Go 后台接口别只测 200:JWT、RBAC 和 tenant_id 怎么验
开发语言·后端·golang
এ慕ོ冬℘゜13 小时前
前端基础:什么是时间戳?JS获取时间戳三种方法与实战用途
开发语言·前端·javascript
执明wa13 小时前
LayoutInflater详解: XML是如何变成View的?
android·xml·开发语言·android studio