ランダム値を生成する
乱数を生成する
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();
}
}
範囲内の乱数を生成する
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));
}
Uniform は uniform 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 クレートの乱数は 一様分布 に従います。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);
}
カスタム型のランダムな値を生成する
タプル (i32, bool, f64) と、ユーザー定義型 Point の変数をランダムに生成します。ランダム生成を可能にするために、StandardUniform に対して型 Point に Distribution トレイトを実装します。
#![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);
}
英数字の文字セットからランダムなパスワードを作成する
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()
}
ユーザー定義の文字セットからランダムなパスワードを作成する
ユーザー定義のカスタムバイト文字列から、指定した長さの 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}");
}