2019-08-28 | 研究与探索 | UNLOCK

rand:Rust随机数库简介

rand是相当基础的Rust crate,是TRPL中第一个被介绍的非标准库。

本文是粗略的简介,想要详细了解可以看 The Rust Rand Book 以及 https://rust-random.github.io/rand

可以通过简单地调用 rand::random() 来获得一个随机值,这是一个泛型函数,需要能够推导出返回类型或者通过 turbo fish 语法显式指定:

1
let v = rand::random::<(u8, f64)>();

更高级的用法涉及到随机数生成器(Random Number Generator, RNG),在 rand 中表示为 Rng trait。这个类型的对象能不断生成一个个随机数。通过对生成的随机数进行一些处理,我们可以获得我们想要性质的随机数序列,比如符合某个随机分布、以某个概率生成随机数等。

大多数情况下rand::thread_rng返回的随机数生成器就够用了。

这里介绍部分 Rng 提供的常用方法:

  • fn gen<T>(&mut self) -> T
    生成一个 T 类型的随机值
  • fn gen_range<T: SampleUniform, B1, B2>(&mut self, low: B1, high: B2) -> T
    生成区间 [low, high) 中的随机值,这个特别常用,比如很容易就能生成一个 60 到 100 之间的及格分数:

    1
    2
    let mut rng = rand::thread_rng();
    let passed_score : u32 = rng.gen_range(60, 101);

    作为对比,在C语言中你得写 rand() % (101-60) + 60

  • fn gen_bool(&mut self, p: f64) -> bool fn gen_ratio(&mut self, numerator: u32, denominator: u32) -> bool
    这两个函数都是指定概率生成 bool 值, gen_boolp 指定返回 true 的概率, gen_ratio 返回 true 的概率被指定为 $\frac{numerator}{denominator}$ 。

rand::seq 封装了关于序列(切片和迭代器)的随机方法。

对切片有 rand::seq::SliceRandom trait,典型方法有:

  • fn choose<R: ?Sized>(&self, rng: &mut R) -> Option<&Self::Item>
    随机选择切片中一个元素
  • fn choose_multiple<R: ?Sized>( &self, rng: &mut R, amount: usize ) -> SliceChooseIter<Self, Self::Item>
    无重复地以随机顺序随机选择切片中 amount 个元素,返回符合 Item=&T 的迭代器。
  • fn shuffle<R: ?Sized>(&mut self, rng: &mut R)
    随机重排整个切片中元素。

对迭代器有 rand::seq::IteratorRandom trait。它的常用方法如下:

  • fn choose<R: ?Sized>(self, rng: &mut R) -> Option<Self::Item>
    SliceRandom::choose 类似。
  • fn choose_multiple<R: ?Sized>( self, rng: &mut R, amount: usize ) -> Vec<Self::Item>
    SliceRandom::choose_multiple 类似,但是返回一个包含了所选元素的 Vec ,而且不保证其中元素的顺序的随机性,如果需要保证随机顺序,要再 shuffle 一次。

rand 还有 distribution (概率分布)的相关用法,这里就不说了。