🚴‍♀️

randを用いたRustの簡単な乱数メモ

2024/04/25に公開


スクラップにメモしていたシリーズです。randクレートで乱数生成する方法を調べた結果のメモです。[rand "0.8.5"]

前提

Cargo.toml
[dependencies]
rand = "0.8.5"

サンプルコード

use rand::prelude::*;

fn main() {
    // random<T>() is shortcut of thread_rng().gen()
    if random() { // generates a boolean
        let _ = random::<f64>(); // generates a float between 0 and 1
    }

    let mut rng1: ThreadRng = thread_rng();
    let _foo: u32 = rng1.gen_range(4_u32..9);
    let _bar: i32 = rng1.gen_range(-5..=5);
    let _baz: f64 = rng1.gen_range(1.0..2.0);
    let _qux: bool = rng1.gen_ratio(2_u32, 3); // probability of true is about 67%

    // generates with seed
    let seed: [u8; 32] = [0; 32];
    let mut rng2: StdRng = StdRng::from_seed(seed);
    let _ = rng2.gen::<f64>();

    // random sort
    let mut vec: Vec<i32> = (1..10).collect();
    vec.shuffle(&mut rng1);
    println!("{:?}", vec);
}

メモ

  • 4種類の生成器がある
    • OsRng, ThreadRng, StdRng, SmallRng
  • StdRngSmallRngは将来のリリースでアルゴリズムが変わる可能性がある
  • rand_distrクレートを使用すると標準偏差など乱数を偏らせることができる

おまけ

  • 以下の場合に使用可能な代替方法
    • セキュアさが明確に不要
    • 人間にとって乱数のように感じるだけでいい
    • クレートを追加するほどでもないショボい用途
fn main() {
    if get_random_like_bool() {
        println!("{}", get_random_like_digit());
    }
}
fn get_random_like_bool() -> bool { get_time_uint() % 2 > 0 }
fn get_random_like_digit() -> u128 { get_time_uint() % 10 }
fn get_time_uint() -> u128 {
    use std::time::{SystemTime, UNIX_EPOCH};
    SystemTime::now().duration_since(UNIX_EPOCH).unwrap_or_default().as_nanos()
}

参考文献

Discussion