Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

ランダム値を生成する

乱数を生成する

rand-badge cat-science-badge

rand::rng() を介して取得した乱数生成器 rand::Rng を使って乱数を生成します。各スレッドには初期化済みの生成器があります。整数はその型の範囲にわたって一様に分布し、浮動小数点数は 0 以上 1 未満で一様に分布します。

use rand::RngExt;

fn main() {
    let mut rng = rand::rng();
    let random_number: u32 = rng.random();
    println!("Random number: {random_number}");
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_random_number() {
        let mut rng = rand::rng();
        let _: u32 = rng.random();
    }
}

範囲内の乱数を生成する

rand-badge cat-science-badge

Rng::random_range を使って、半開区間 [0, 10)10 は含まない)内のランダムな値を生成します。

use rand::RngExt;

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

Uniformuniform distribution に従う値を取得できます。これも同じ効果がありますが、同じ範囲で繰り返し数値を生成する場合は、より高速になることがあります。

use rand_distr::{Distribution, Uniform};

fn main() {
    let mut rng = rand::rng();
    let die =
        Uniform::new_inclusive(1, 6).expect("Failed to create uniform distribution: invalid range");

    loop {
        let throw = die.sample(&mut rng);
        println!("Roll the die: {}", throw);
        if throw == 6 {
            break;
        }
    }
}

指定した分布に従う乱数を生成する

rand_distr-badge cat-science-badge

デフォルトでは、rand クレートの乱数は 一様分布 に従います。rand_distr クレートは ほかの種類の分布を提供します。これらを使うには、分布をインスタンス化し、その後、 乱数生成器 rand::Rng を使って Distribution::sample によりその分布から サンプリングします。

利用可能な分布のドキュメントはこちらです。Normal 分布を使う例を 以下に示します。

use rand_distr::{Distribution, LogNormal, Normal};

fn main() {
    let mut rng = rand::rng();
    let normal = Normal::new(2.0, 3.0).expect("Failed to create normal distribution");
    let log_normal = LogNormal::new(1.0, 0.5).expect("Failed to create log-normal distribution");

    let v = normal.sample(&mut rng);
    println!("{} is from a N(2, 9) distribution", v);
    let v = log_normal.sample(&mut rng);
    println!("{} is from an ln N(1, 0.25) distribution", v);
}

カスタム型のランダムな値を生成する

rand-badge cat-science-badge

タプル (i32, bool, f64) と、ユーザー定義型 Point の変数をランダムに生成します。ランダム生成を可能にするために、StandardUniform に対して型 PointDistribution トレイトを実装します。

#![allow(dead_code)]
use rand::{Rng, RngExt};

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

impl Point {
    fn random<R: Rng>(rng: &mut R) -> Self {
        Point {
            x: rng.random(),
            y: rng.random(),
        }
    }
}

fn main() {
    let mut rng = rand::rng();
    let rand_tuple = rng.random::<(i32, bool, f64)>();
    let rand_point = Point::random(&mut rng);
    println!("Random tuple: {:?}", rand_tuple);
    println!("Random Point: {:?}", rand_point);
}

英数字の文字セットからランダムなパスワードを作成する

rand-badge cat-os-badge

Alphanumeric サンプルを使用して、A-Z, a-z, 0-9 の範囲にある ASCII 文字から、指定した長さの文字列をランダムに生成します。

use rand::{distr::Alphanumeric, RngExt};

fn main() {
    let password = generate_password();
    println!("{password}");
}

fn generate_password() -> String {
    const PASSWORD_LEN: usize = 30;
    let mut rng = rand::rng();

    (0..PASSWORD_LEN)
        .map(|_| rng.sample(Alphanumeric) as char)
        .collect()
}

ユーザー定義の文字セットからランダムなパスワードを作成する

rand-badge cat-os-badge

ユーザー定義のカスタムバイト文字列から、指定した長さの ASCII 文字列を random_range を使用してランダムに生成します。

use rand::RngExt;

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

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

    let password: String = (0..PASSWORD_LEN)
        .map(|_| {
            let idx = rng.random_range(0..CHARSET.len());
            char::from(CHARSET[idx])
        })
        .collect();

    println!("{password}");
}