四时宝库

程序员的知识宝库

「Rust笔记」Rust生成随机数的方法

1、前言

在项目当中,生成随机数、随机密码等经常会使用到。这里总结下Rust随机数生成的方法。Rust我们要用到包模块 rand。具体实现如下:

2、添加模块依赖

[dependencies]
rand="0.7.9"

1、生成随机数

利用rand::Rng 库,通过 rand::thread_rng 生成随机数。可以开启多个线程,每个线程都有一个初始化的生成器。整数在其类型范围内均匀分布,浮点数是从 0 均匀分布到 1,但不包括 1

use rand::Rng;

fn main() {
    let mut rng = rand::thread_rng();
    let r1: u8 = rng.gen();
    let r2: u16 = rng.gen();
    println!("Random u8: {}", r1);
    println!("Random u16: {}", r2);
    println!("Random u32: {}", rng.gen::<u32>());
    println!("Random i32: {}", rng.gen::<i32>());
    println!("Random float: {}", rng.gen::<f64>());
}

运行结果

Random u8: 161
Random u16: 64516
Random u32: 491427136
Random i32: -1045543914
Random float: 0.8811496121121281

2、生成范围内的随机数

使用 Rng::gen_range,在半开放的 [0, 10) 范围内(不包括 10)生成一个随机值。

use rand::Rng;

fn main() {
    let mut rng = rand::thread_rng();
    println!("Integer: {}", rng.gen_range(0, 10));
    println!("Float: {}", rng.gen_range(0.0, 10.0));
}

运行结果

Integer: 6
Float: 5.37451821096689

使用 Uniform 模块可以得到均匀分布的值。下述代码和上述代码具有相同的效果,但在相同范围内重复生成数字时,下述代码性能可能会更好。

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

fn main() {
    let mut rng = rand::thread_rng();
    let die = Uniform::from(1..7);
    let throw = die.sample(&mut rng);
    println!("res: {}", throw);
}

运行结果

res: 4

3、生成给定范围的随机数

默认情况下,随机数在 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, 3.0)?;
    let v = normal.sample(&mut rng);
    println!("distribution {}", v);
    Ok(())
}

运行结果

distribution -0.12783970058837957

4、生成自定义类型随机数

随机生成一个元组 (i32, bool, f64) 和用户定义类型为 Point 的变量。

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!("Random tuple: {:?}", rand_tuple);
    println!("Random Point: {:?}", rand_point);
}

运行结果

Random tuple: (-1868810826, false, 0.8721302896776749)
Random Point: Point { x: 1991073034, y: 1644146453 }

5、字母数字生成随机数

随机生成一个给定长度的 ASCII 字符串,范围为 A-Z,a-z,0-9

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

运行结果

9Eicos7eWr6rFduM0EY33kGfrQifYJ

6、根据用户自定义字符生成随机数

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

fn main() {
    use rand::Rng;
    const CHARSET: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
                            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);
}

运行结果

"e*IdXR3kQk8ZdJ1mslTdFq9ofn~mMT"

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言
    友情链接