Why not login to Qiita and try out its useful features?

We'll deliver articles that match you.

You can read useful information later.

9
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【2026年最新版】 Rustで乱数: randクレート v0.10.0 時代の最速ガイド

9
Last updated at Posted at 2026-03-08

ちなみに人生初記事でっす。高校入るときのいい土産になったかも?

はじめに:なぜ「今」この記事が必要なのか

Rust で乱数を扱おうとして検索すると、多くの素晴らしい解説記事に出会います。しかし、そこで紹介されているコードを最新の環境で動かしようとすると、コンパイルエラーに直面することが少なくありません。その原因の多くは、Rust の主要な乱数クレートである rand のバージョンアップに伴う API の変更にあります。本記事では、初心者が「今」最短ルートで乱数を使いこなせるよう、最新バージョンに基づいた正しい書き方を解説します。

準備:30秒で終わるセットアップ

Rust で乱数を使うには、プロジェクトの設定ファイル(Cargo.toml)に依存関係を追加する必要があります。

[dependencies]
rand = "0.10.0"

この記事で紹介するコードはすべてこのバージョンで動作確認済みですので、安心して学習を進めてください。

【基本】まずはこれだけ:範囲指定で乱数を作る

ここ最近のバージョンアップで最も画期的なのは、乱数生成器(RNG)を明示的に準備することなく、一行で範囲指定の乱数を作れるようになった点(v0.9)です。

例えば「0 から 9 までの整数が欲しい」といった場合、専用の関数を呼び出すだけで済みます。

fn main() {
    // rand 0.10.0 で推奨される 範囲付き乱数生成
    // 0 から 9 までの整数をランダムに生成します
    let n: u8 = rand::random_range(0..10);

    println!("Random number (0-9): {}", n);
}

注目ポイント

  • let n: u8 = rand::random_range(0..10);
    • 解説: 1行で特定の範囲から乱数を取り出せます。非常にラクです。

この際、範囲の指定方法には 2 つの種類があります。

  • 一つは「終端を含まない(0..10)」指定。これは 0 から 9 までを生成します。
  • もう一つは「終端を含む(0..=10)」指定。これは 0 から 10 までを生成します。

2026.3.9追記:範囲指定で気を付けるポイント

コメントつけてくれた@scivola様に感謝

let n: u8 = rand::random_range(0..256);

とすると、

error: range endpoint is out of range for `u8`
 --> src/main.rs:6:34
  |
4 |     let n: u8 = rand::random_range(0..256);
  |                                  ^^^^^^ help: use an inclusive range instead: `0..=255`
  |

となります。u8の範囲を超えないように、

let n: u8 = rand::random_range(0..=255);

とする必要があります。

コード例

基本を理解したら、よく使うパターンを見ていきましょう。

そのいち:乱数生成器(RNG)を取得して使い回す

複数の乱数を続けて生成する場合やループ内で使用する場合は、一度生成器を取得するのが一般的です。

use rand::prelude::*;

fn main() {
    // 1. RNG (乱数生成器) インスタンスを取得
    let mut rng = rand::rng();

    // 2. 生成器を使って複数の乱数を作る
    let a: u32 = rng.random();
    let b: f64 = rng.random_range(0.0..1.0);

    println!("Random u32: {}", a);
    println!("Random f64: {}", b);

    // 3. ループ内での再利用
    print!("Dice rolls: ");
    for _ in 0..5 {
        let die_roll = rng.random_range(1..=6);
        print!("{} ", die_roll);
    }
    println!();
}

注目ポイント

  • let mut rng = rand::rng();
    • 解説: 現在のスレッドに紐付いた乱数生成器を取得します。内部状態を更新するため、必ず mut 修飾子が必要です。
  • let a: u32 = rng.random();
    • 解説: 指定した型の範囲全体(u32 なら 0〜42億強)から乱数を生成します。
  • let b: f64 = rng.random_range(0.0..1.0);
    • 解説: インスタンスメソッド版の範囲指定生成です。ループ内で何度も生成する場合はこちらの方が効率的です。

そのに:0.0〜1.0 の浮動小数点を生成する

ゲームの確率判定などでよく使われる手法です。

use rand::prelude::*;

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

    // 0.0 以上 1.0 未満の f64 乱数を生成
    let f: f64 = rng.random();

    println!("Random f64 (0.0-1.0): {}", f);

    // 確率判定の例 (25% の確率で成功)
    if f < 0.25 {
        println!("Success! (25% chance)");
    }
}

注目ポイント

  • let f: f64 = rng.random();
    • 解説: f64 型を指定して生成すると、自動的に 0.0 以上 1.0 未満の範囲の値が返されます。確率判定の王道パターンです。

そのさん:リストの中身をシャッフルする

トランプの配札や、データの順序をバラバラにしたい時に使います。

use rand::prelude::*;

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

    let mut numbers = vec![1, 2, 3, 4, 5];

    // その場で要素をランダムに入れ替えます
    numbers.shuffle(&mut rng);

    println!("After shuffle: {:?}", numbers);
}

注目ポイント

  • numbers.shuffle(&mut rng);
    • 解説: SliceRandom トレイトが提供するメソッドで、ベクタや配列の要素を直接(in-place)並べ替えます。

そのし:リストから要素を 1 つ選ぶ

「おみくじ」のように、リストの中からランダムに一つだけ中身を取り出す方法です。

use rand::prelude::*;

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

    let choices = ["Apple", "Banana", "Cherry", "Durian"];

    // ランダムに1つの要素を安全に(Option型で)取得します
    if let Some(choice) = choices.choose(&mut rng) {
        println!("Today's snack: {}", choice);
    }
}

注目ポイント

  • choices.choose(&mut rng)
    • 解説: リストからランダムに1つの要素への参照を返します。リストが空の場合を考慮して Option<&T> 型を返す安全な設計になっています。

そのご:重みに基づいて選択する(ガチャの確率設定)

「レアアイテムは 1%、ノーマルアイテムは 85%」のように、特定の確率(重み)に従ってランダムに選択する方法です。

use rand::distr::{Distribution, weighted::WeightedIndex};

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

    let items = ["Normal", "Rare", "SuperRare"];
    let weights = [85, 14, 1]; // 重みの比率

    // 重みに基づいたインデックス生成器を作成
    let dist = WeightedIndex::new(weights).unwrap();

    // インデックス(0, 1, 2)を取得して対応するアイテムを表示
    let idx = dist.sample(&mut rng);
    println!("Result: {}", items[idx]);
}

注目ポイント

  • let dist = WeightedIndex::new(weights).unwrap();
    • 解説: 重みのリストから「インデックスの分布」を作成します。合計が 0 の場合などはエラーになるため、実戦では適切なエラー処理が推奨されます。
  • dist.sample(&mut rng);
    • 解説: 定義した重みに基づいて、インデックス番号(0, 1, 2...)を 1 つ取り出します。

そのろく:再現性が欲しい:シードを指定して固定する

デバッグ中や科学計算では、実行するたびに結果が変わると困る場合があります。特定の「シード値」を与えることで、常に同じ乱数の列を生成できます。

use rand::prelude::*;
use rand::rngs::StdRng;

fn main() {
    let seed: u64 = 42;

    // 特定のシードから RNG インスタンスを作成
    let mut rng = StdRng::seed_from_u64(seed);

    let n: u32 = rng.random();
    println!("Seeded random: {}", n); // 常に同じ値が出力される
}

注目ポイント

  • StdRng::seed_from_u64(seed);
    • 解説: 予測可能な(固定された)シードから生成器を初期化します。同じシードを使えば、どの環境でもまったく同じ乱数列が再現されます。

落とし穴:初心者がハマる「よくある間違い」

学習中にエラーが出た際、以下のポイントをチェックしてみてください。

  • 古い API の使用: gen_range というメソッドは、古いバージョンでは主流でしたが、最新版では random_range 関数やメソッドに置き換わっています。
  • インポートの不足: shufflechoose を使うには、use rand::prelude::*; を含めて必要なトレイトを読み込む必要があります。
  • 状態の更新: 乱数生成器から値を取り出す際、生成器自身の内部状態が更新されます。そのため、生成器を保持する変数には「変更可能(mut)」という印が必要です。

さらに高度な話題:ガウス分布

専門的な統計処理が必要な場合、平均と標準偏差を指定したサンプリング(正規分布)も可能です。この機能を利用するには、追加で rand_distr クレートを導入するのが一般的です。

[dependencies]
rand = "0.10.0"
rand_distr = "0.6.0"
use rand_distr::{Distribution, Normal};

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

    // 平均 0.0、標準偏差 1.0 のガウス分布を作成
    let normal = Normal::new(0.0, 1.0).unwrap();

    let v: f64 = normal.sample(&mut rng);
    println!("Normal distribution sample: {:.4}", v);
}

注目ポイント

  • let normal = Normal::new(0.0, 1.0).unwrap();
    • 解説: 平均(mean)と標準偏差(std dev)を指定して分布を定義します。
  • normal.sample(&mut rng);
    • 解説: 定義した分布に従って値を 1 つサンプリングします。

まとめ

乱数の世界はめんどくさく奥が深く、より複雑な統計分布や、高いセキュリティが求められる暗号学的用途など、さらに高度なトピックも存在します。公式の「Rand Book」や、詳細なリファレンスである「Docs.rs」のページを覗いてみてください。

補足:rand crateはバージョンアップでどこが変わったのでしょう

2026.3.9追記:AIに主な変更点書かせてみた

ちょくちょく筆者にもわからん単語が飛んでます。

0.6.0 (2018-11-14)
機能追加と最適化

  • SmallRng: アルゴリズムとして PCG を導入。
  • シーケンス: WeightedIndex(重み付きサンプリング)の追加。
  • SIMD: SIMD 型の生成サポートの開始。

0.7.0 (2019-06-28)
アーキテクチャの再設計と外部切り出し

  • Edition 2018: Rust Edition 2018 への移行。
  • OS インターフェースの分離: OS の乱数生成機能が getrandom クレートとして独立。
  • 分布の外部化: 多くの特殊な分布が rand_distr クレートへ移動され、rand 本体は軽量化されました。
  • StdRng: ChaCha アルゴリズムを採用。

0.8.0 (2020-12-18) (検索するとよく出てくる)
構文の改善とアルゴリズムの更新

  • 範囲指定の変更: gen_range(a, b) が gen_range(a..b) のレンジ構文に変更されました。
  • SmallRng の変更: アルゴリズムが PCG から xoshiro へ変更。
  • Alphanumeric: 従来の char ではなく u8 (bytes) を生成するように変更。
  • OS サポート: getrandom v0.2 へのアップデート。

0.9.0 (2025-01-27)
API の使いやすさ向上と 2024 Edition への準備

  • トップレベル関数の刷新: thread_rng() が rng() に、Rng::gen() が random() に改称されました(Rust 2024 の gen
    キーワードとの衝突回避のため)。
  • 便利な関数の追加: random_range, random_bool, random_iter などのトップレベル関数が導入され、rng().random_range(1..10)
    のように直感的に書けるようになりました。
  • モジュール構造の整理: distributions モジュールが distr に短縮され、Standard 分布が StandardUniform に改称。
  • フィーチャー名の変更: serde1 → serde、getrandom → os_rng。

0.10.0 (2026-02-08) - 最新
リネームとサポート環境のモダン化

  • 依存関係の変更: rand_chacha から chacha20 へ移行(StdRng の実装が変更)。
  • 用語の統一: choose_multiple が sample に、os_rng が sys_rng にリネームされました。
  • トレイトの再定義: rand_core で RngCore が Rng に改称された影響で、rand の Rng トレイトは RngExt へリネームされました。
  • Rust Edition 2024: Edition 2024 への移行と MSRV 1.85 への引き上げ。
  • 追加: ジェネリックに RNG を作成する rand::make_rng() の導入。
  • 削除: ReseedingRng および small_rng フィーチャーの削除。

最後に一つだけ。「必ず自分の手で動かして確認すること」を忘れずに!

9
2
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up

@EngineerNissie's pickup articles

EngineerNissie

@EngineerNissie(Nissie)

高校生になってしまった…

Comments

scivola
@scivola

範囲指定に関して

let n: u8 = rand::random_range(0..=255);

はできても

let n: u8 = rand::random_range(0..256);

はできない,ということは一言あってもいいかもしれませんね。
(後者は「range endpoint is out of range for u8」になる)

1
EngineerNissie
@EngineerNissie(Nissie)

コメントありがとうございます

0

Let's comment your feelings that are more than good

9
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Login to continue?

Login or Sign up with social account

Login or Sign up with your email address