随机数使用

随机数

随机数的生成对于很多随机数算法非常重要

在C++中,mt19937_64srand(time(0))(配合rand())是两种不同的随机数生成方式,它们分别属于现代C++随机数库和传统的C风格随机数生成方法。以下是它们的详细介绍、区别以及适用场景。


  1. mt19937_64(梅森旋转算法)
    特点
  • 高质量随机数:基于梅森旋转算法(Mersenne Twister),周期极长((2^{19937}-1)),适用于需要高质量随机数的场景。
  • 64位随机数:生成的是64位无符号整数(uint64_t),范围更大。
  • 现代C++风格:属于<random>库,支持多种随机分布(均匀分布、正态分布等)。
  • 线程安全:每个mt19937_64实例独立运行,适合多线程环境。

基本用法

#include <random>
#include <iostream>
 
int main() {
    std::mt19937_64 rng(std::random_device{}()); // 使用随机设备初始化种子 也可用mt19937_64 rnd(time(0))
    for (int i = 0; i < 5; i++) {
        std::cout << rng() << "\n"; // 生成64位随机数 
    }
    return 0;
}

输出示例

14514284786278117030 
4620546740167642908 
13199598094361884370 
16793137390881808272 
...

适用场景

  • 密码学(需要高质量随机数)
  • 模拟仿真(需要长周期随机数)
  • 哈希函数(如本题的随机哈希)
  • 游戏开发(随机地图生成、AI行为)

  1. srand(time(0)) + rand()(传统C随机数)
    特点
  • 简单易用:属于C标准库(<cstdlib>),代码简短。
  • 低质量随机数:基于线性同余生成器(LCG),周期较短(通常 (2^{31})),随机性较差。
  • 32位随机数:rand()返回int,范围通常是0RAND_MAX(通常32767)。
  • 全局状态:srand()设置种子后,所有rand()调用共享同一个状态,不适合多线程。

基本用法

#include <cstdlib>
#include <ctime>
#include <iostream>
 
int main() {
    std::srand(std::time(0)); // 用当前时间初始化种子 
    for (int i = 0; i < 5; i++) {
        std::cout << std::rand() << "\n"; // 生成随机数 
    }
    return 0;
}

输出示例

1804289383 
846930886 
1681692777 
1714636915 
...

适用场景

  • 简单随机需求(如随机排序、简单游戏)
  • 快速原型开发(不需要高质量随机数)
  • 教学示例(因为代码简单)

  1. 关键区别
    | 特性 | mt19937_64 | srand(time(0)) + rand() |
    |------|-------------|----------------|
    | 随机性质量 | 高(梅森旋转) | 低(线性同余) |
    | 周期长度 | (2^{19937}-1) | (2^{31}) |
    | 生成位数 | 64位 | 32位 |
    | 随机数范围 | 0 ~ (2^{64}-1) | 0 ~ RAND_MAX(通常32767) |
    | 线程安全 | 是(每个实例独立) | 否(全局状态) |
    | 现代C++支持 | 是(<random>) | 否(C风格) |

  1. 如何选择?
    | 场景 | 推荐方法 |
    |------|---------|
    | 需要高质量随机数(哈希、密码学) | mt19937_64 |
    | 多线程环境 | mt19937_64(每个线程独立实例) |
    | 简单随机需求(如随机排序) | rand() |
    | 需要特定分布(如正态分布) | <random>库(std::normal_distribution) |
    | 兼容旧代码 | rand() |

  1. 代码示例对比
    (1) 生成随机数
// mt19937_64 
std::mt19937_64 rng(std::random_device{}());
u64 random_num = rng();
 
// rand()
std::srand(std::time(0));
int random_num = std::rand();

(2) 生成范围随机数

// mt19937_64 + 均匀分布 
std::uniform_int_distribution<int> dist(1, 100);
int num = dist(rng);
 
// rand() 取模(不推荐,有偏差)
int num = std::rand() % 100 + 1; // 可能不均匀 

(3) 生成浮点数

// mt19937_64 + 均匀浮点分布 
std::uniform_real_distribution<double> dist(0.0, 1.0);
double num = dist(rng);
 
// rand() 转换(不推荐)
double num = (double)std::rand() / RAND_MAX; // 精度低 

  1. 结论
  • 优先使用<random>库(mt19937_64),因为:
    • 随机性更好
    • 支持多种分布
    • 线程安全
  • rand()仅适用于简单需求,如:
    • 快速测试
    • 旧代码兼容
    • 不需要高质量随机数的场景
posted @ 2025-06-13 18:15  归游  阅读(103)  评论(0)    收藏  举报