[Rust] 整数の乱数を生成する

  • 2022年9月25日
  • 2022年9月26日
  • Rust
  • 179View
  • 0件

整数乱数の生成

Rust の標準ライブラリには乱数生成モジュールは含まれないため、外部の rand crate を利用する必要があります。

動作環境

  • Windows 11
  • WSL Ubuntu 20.04
  • Rust 1.64.0

サンプルプロジェクトの作成

今回利用するサンプルプロジェクトを作成します。

$ cargo new rand-sample

依存パッケージに rand を追加します。

[package]
name = "rand-sample"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
rand = "0.8.5"

整数乱数の生成 その1

乱数を生成するための最も単純な方法は rand::random を呼び出すことです。

fn main() {
    println!("{}", rand::random::<i32>());
    println!("{}", rand::random::<i32>());
    println!("{}", rand::random::<i32>());
}
$ cargo run
1014175463
-1118522608
-233617653

整数乱数の生成 その2

より実用的には、rand::thread_rng() を呼び出します。
rng はおそらく、Random Number Generator の略です。

その1で利用した rand::random は、rand::thread_rng().gen() を簡易的に実行するものであり、乱数シードによる初期化のオーバーヘッドが毎回発生してしまいます。

rand::thread_rng() を利用することで、初期化と乱数生成を分離して実行することができます。

use rand::Rng;

fn main() {
    let mut rng = rand::thread_rng();
    println!("{}", rng.gen::<i32>());
    println!("{}", rng.gen::<i32>());
    println!("{}", rng.gen::<i32>());
}
$ cargo run
1824664652
909867432
-767794661

実行時間比較

rand::randomrand::thread_rng の実行時間を比較してみます。
それぞれの手法に対して、1億回乱数を生成させた時間を計測します。

rand::random 実行時間

fn main() {
    let mut v = Vec::<i32>::new();
    for _ in 0..100_000_000 {
        v.push(rand::random());
    }
}
$ time cargo run
real    0m36.066s
user    0m35.975s
sys     0m0.090s

rand::random では 36 秒の時間を要しました。

rand::thread_rng 実行時間

use rand::Rng;

fn main() {
    let mut v = Vec::<i32>::new();
    let mut rng = rand::thread_rng();
    for _ in 0..100_000_000 {
        v.push(rng.gen());
    }
}
$ time cargo run
real    0m28.514s
user    0m28.413s
sys     0m0.100s

rng を生成して rng.gen を実行する手法では、28.5 秒の時間を要しました。
thread_rng の方が実行効率が良いことがわかります。

範囲指定の乱数生成

Rng に対して gen_range メソッドを呼び出すことで、乱数の範囲を指定することもできます。

次の例では、0 以上 10 未満の整数を3回生成しています。

use rand::Rng;

fn main() {
    let mut rng = rand::thread_rng();
    println!("{}", rng.gen_range(0..10));
    println!("{}", rng.gen_range(0..10));
    println!("{}", rng.gen_range(0..10));
}
$ cargo run
7
1
4

【関連記事】

rand crate を利用することで、整数型以外の乱数も生成可能です。
例として、以下の記事では浮動小数点数の乱数を生成しています。