5.1.1. 生成随机数

rand-badge cat-science-badge

问题:

你想取得某个标量类型的随机数。

解决方案:

Rust 生态中,有一个比较成熟的随机值计算库 rand crate,提供了各类扩展 trait 和随机值计算的方法。在随机数生成器 rand::Rng 的帮助下,通过 rand::thread_rng 生成随机数。

并且,可以开启多个线程,每个线程都可以存在一个初始化的生成器。整数在其类型范围内均匀分布,浮点数是从 0 均匀分布到 1,但不包括 1。

以下实例代码引用自开源书籍项目《Cookin’ with Rust》,笔者在其基础上稍作修改。

use rand::Rng; // `RngCore` 上自动实现的扩展 trait,实现了高层次的泛型方法

fn main() {
    let mut rng = rand::thread_rng(); // 由系统创建的本地线程,是延迟初始化的随机数生成器

    let n1: u8 = rng.gen(); // 返回一个支持标准分布的随机值
    let n2: u16 = rng.gen();
    
    println!("  u8    随机数: {}", n1);
    println!("  u16   随机数: {}", n2);
    
    println!("  u32   随机数: {}", rng.gen::<u32>());
    println!("  i32   随机数: {}", rng.gen::<i32>());
    println!("  float 随机数: {}", rng.gen::<f64>());
}

代码第 1 行,我们使用 use 关键字将 rand::Rng 引入作用域。rand::Rng 是在 RngCore trait 上自动实现的扩展 trait,它实现了高层次的泛型方法。

代码第 4 行,由系统创建本地线程,作用为延迟初始化的随机数生成器。

代码第 6,7 行,均为返回支持标准分布的随机值,分别是 u8,u16 的无符号整型。

构建并运行后,结果大抵如下所示。

  u8    随机数: 73
  u16   随机数: 36982
  u32   随机数: 2372946688
  i32   随机数: 17124411
  float 随机数: 0.8223380141339609

注:你的运行结果值和笔者运行结果不一定相同。

讨论:

rand::RngRngCore 上自动实现的扩展 trait,为抽样取值和其它便捷方法实现了高层次的泛型方法。

rand::thread_rng 是创建随机数生成器线程的函数。调用后,由系统创建延迟初始化的本地线程。随机生成器线程将用于方法链(method chaining)样式,如 thread_rng().gen::<i32>()。或本地缓存,如 let mut rng = thread_rng();。由 Default trait 调用,等效于 ThreadRng::default()