通过例子学习Rust

49.4 随机数

The std::rand module provides access to the Random Number Generators (RNG) provided by the OS, which can then be used to generate random values of any type that implements the Rand trait (which includes all the primitive types).

// gen.rs
use std::rand::Rng;
use std::rand;

fn main() {
    // create a task-local Random Number Generator
    let mut rng = rand::thread_rng();

    // the `gen` methods generates values in the full range of each type using
    // a uniform distribution
    println!("randomly generate some values for different primitive types");
    println!("u8: {}", rng.gen::<u8>());
    println!("i8: {}", rng.gen::<i8>());
    println!("u16: {}", rng.gen::<u16>());
    println!("i16: {}", rng.gen::<i16>());
    // except for floats which get generated in the range [0, 1>
    println!("f32: {}", rng.gen::<f32>());
    println!("f64: {}", rng.gen::<f64>());

    // `gen_iter` returns an iterator that yields a infinite number of randomly
    // generated numbers
    let mut v: Vec<u8> = rng.gen_iter::<u8>().take(10).collect();

    println!("10 randomly generated u8 values");
    println!("{}", v.as_slice());

    // `shuffle` shuffles a mutable slice in place
    rng.shuffle(v.as_mut_slice());
    println!("shuffle previous slice");
    println!("{}", v.as_slice());

    // `choose` will sample an slice *with* replacement
    // i.e. the same element can be chosen more than one time
    println!("sample previous slice *with* replacement 10 times");
    for _ in range(0u, 10) {
        match rng.choose(v.as_slice()) {
            None => panic!("slice was empty"),
            Some(x) => println!("{}", x),
        }
    }
}

{gen.out}

Several structs are available under the std::rand::distributions module, that can be used to generate values using different probability distributions like: normal, uniform, Student's T, Chi squared, Gamma, etc.

// distributions.rs
use std::rand::distributions::{IndependentSample,Normal,StudentT};
use std::rand;

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

    let normal = Normal::new(0.0, 1.0);
    println!("10 samples from a normal distribution with mean 0.0 and SD 1.0");
    for _ in range(0u, 10) {
        println!("{}", normal.ind_sample(&mut rng));
    }

    let student = StudentT::new(5.0);
    println!("10 samples from a T distribution with 5 degrees of freedom");
    for _ in range(0u, 10) {
        println!("{}", student.ind_sample(&mut rng));
    }
}

{distributions.out}

The deriving attribute can be used to implement the Rand trait for custom types, this allows generation of random values of custom types.

// deriving.rs
use std::rand;
use std::rand::Rng;

#[deriving(Rand,Show)]
struct Point {
    x: f64,
    y: f64,
}

#[deriving(Rand,Show)]
struct Rectangle {
    p1: Point,
    p2: Point,
}

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

    println!("random point\n{}", rng.gen::<Point>());
    println!("random rectangle\n{}", rng.gen::<Rectangle>());
}

{deriving.out}