Rust-高级-Crate之rand

  1. 基础
  2. 范围取值
  3. 分布随机数
  4. 配置其他分布
  5. 自定义类型随机数
  6. 获取随机字母
  7. 自定义字符创建随机数

基础

用于获取随机值的计算库。
通过rand::Rng随机数生成器,来获取随机值。并且可以开启多线程工作。

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>());
}

范围取值

通过gen_range来获取指定范围内的随机值,范围左闭右开。

use rand::Rng;

fn main() {
let mut rng = rand::thread_rng();

println!(" 整数: {}", rng.gen_range(0..10)); // 半开放范围取随机值,即包括`低位`而不包括`高位`
println!(" 浮点数: {}", rng.gen_range(0.0..10.0));
}

分布随机数

rend 提供了均匀分布采样的功能,这些函数可能会预先做一些额外的工作,以便更快地对多个值进行采样。

均匀分布:在概率论和统计学中,均匀分布也叫矩形分布,它是对称概率分布,在相同长度间隔的分布概率是可能相等的。

use rand::distributions::{Distribution, Uniform};

fn main() {
let mut rng = rand::thread_rng();
let die = Uniform::from(1..7);

loop {
let throw = die.sample(&mut rng);

println!(" 丢一次骰子: {}", throw);

if throw == 6 {
break;
}
}
}

配置其他分布

默认情况下,随机数在 rand crate 中是均匀分布。对其做补充的 rand_distr crate 提供了其它的分布类型。

use rand_distr::{Distribution, Normal, NormalError};
use rand::thread_rng;

fn main() -> Result<(), NormalError> {
let mut rng = thread_rng();
let normal = Normal::new(2.0, 9.0)?; // 正态分布
let v = normal.sample(&mut rng);

println!(" 正态分布: {}", v);

Ok(())
}

rand_distr crate 是 rand::distributions 模块的一个超级集合,实现了诸多概率分布类型,如均匀分布、正态分布(Normal distribution)、柯西分布(Cauchy distribution)等。

自定义类型随机数

对于元组可以使用rng.gen::<(i32, bool, f64)>()直接生成。
对于结构体,可以为其添加Distribution trait特性生成。

use rand::Rng;
use rand::distributions::{Distribution, Standard};

#[derive(Debug)]
struct Point {
x: i32,
y: i32,
}

impl Distribution<Point> for Standard {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Point {
let (rand_x, rand_y) = rng.gen();
Point {
x: rand_x,
y: rand_y,
}
}
}

fn main() {
let mut rng = rand::thread_rng();
let rand_tuple = rng.gen::<(i32, bool, f64)>();
let rand_point: Point = rng.gen();

println!(" 随机值元组: {:?}", rand_tuple);
println!(" 随机值结构体: {:?}", rand_point);
}

获取随机字母

在 rand crate 的分布类型中,包含一个字母数字样本,范围为 A-Z,a-z,0-9。因此我们可以使用字母数字样本,随机生成一个给定长度的 ASCII 字符串。

use rand::{thread_rng, Rng};
use rand::distributions::Alphanumeric;

fn main() {
let rand_string: String = thread_rng()
.sample_iter(&Alphanumeric)
.take(30)
.collect();

println!(" 随机密码: {}", rand_string);
}

其中 rand::distributions::Alphanumeric 是字母数字样本,范围为 A-Z,a-z,0-9。sample_iter 方法迭代从字母数字样本产生总长度为 30 的随机密码。

自定义字符创建随机数

使用用户自定义的字节字符串,使用 gen_range 函数,随机生成一个给定长度的 ASCII 字符串。

use rand::Rng;

fn main() {
const CHARSET: &[u8] = b"abcdefghijklmnopqrstuvwxyz\
0123456789)(*&^%$#@!~";
const PASSWORD_LEN: usize = 30;

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

let password: String = (0..PASSWORD_LEN)
.map(|_| {
let idx = rng.gen_range(0, CHARSET.len()); // 半开放范围取随机值,即包括`低位`而不包括`高位`
CHARSET[idx] as char
})
.collect();

println!(" 随机密码: {:?}", password);
}