「1から100のランダムな数を取得したい」という場面は、プログラミングを学ぶ上で非常によく遭遇する状況です。
乱数生成はゲーム・シミュレーション・統計処理・機械学習・セキュリティなど、現代のソフトウェア開発において欠かせない技術のひとつです。
「ランダムな数を生成する」と聞くと簡単そうに思えますが、実は乱数の仕組みや注意点を正しく理解していないと、バグや脆弱性の原因になることもあります。
本記事では、乱数生成の基本的な考え方・1から100のランダム値を生成するコード例・擬似乱数と真の乱数の違い・アルゴリズムの仕組み・実際の応用例まで、わかりやすく丁寧に解説していきます。
プログラミング初心者の方でも理解できるよう丁寧に説明しますので、ぜひ最後まで読んでみてください。
乱数生成の基本はプログラムで擬似乱数を作ること
それではまず、乱数生成の基本的な仕組みについて詳しく解説していきます。
コンピューターが生成する「乱数」は、実は多くの場合、数学的なアルゴリズムによって生成される「擬似乱数(pseudorandom number)」です。
コンピューターは決定論的な機械であり、同じ入力に対して同じ出力を返す性質を持っています。
そのため、「完全にランダムな数」を生成することは原理的に難しく、代わりに統計的にランダムに見える数列を生成する方法が使われています。
擬似乱数は真の意味でランダムではないものの、見た目上は予測不可能な数列を生成できるため、プログラミングの多くの場面で十分に機能します。
乱数生成の基本知識
擬似乱数(PRNG):数学的アルゴリズムが生成する見た目上のランダム値(通常のプログラムで使用)
真の乱数(TRNG):物理的現象(熱雑音・放射性崩壊・大気ノイズなど)を利用した本当のランダム値
シード値:乱数列の出発点となる初期値(同じシードからは同じ乱数列が生成される)
暗号学的乱数(CSPRNG):セキュリティ用途に使われる予測不可能な擬似乱数
「シード値(seed)」とは、乱数列を初期化するための値のことで、同じシード値を設定すると同じ乱数列が再現される性質があります。
デバッグやテストの再現性を確保したいときはシードを固定し、本番環境では現在時刻や環境変数などを使って毎回異なるシードを設定するのが一般的な方法です。
シード値の管理は、乱数を使うプログラムの品質に直結する重要な要素といえるでしょう。
擬似乱数アルゴリズムの代表例
擬似乱数を生成するアルゴリズムにはさまざまな種類があり、それぞれに特徴があります。
「線形合同法(LCG:Linear Congruential Generator)」は最も古典的なアルゴリズムのひとつで、X_{n+1}=(a×X_n+c) mod mという式で次の乱数を計算します。
計算が軽量であるため、組み込みシステムや昔のゲームコンソールなどで使われてきましたが、統計的な品質は現代の基準では不十分とされることがあります。
「メルセンヌ・ツイスター(Mersenne Twister)」は1997年に松本眞・西村拓士によって開発された高品質な擬似乱数アルゴリズムです。
メルセンヌ・ツイスターは周期が2の19937乗マイナス1という天文学的に膨大な値を持ち、統計的な偏りが非常に少ないのが特徴です。
PythonのrandomモジュールやRなど、多くのプログラミング言語の標準乱数ライブラリで採用されています。
「xorshiftアルゴリズム」は非常に高速な擬似乱数アルゴリズムで、ゲームエンジンや組み込みシステムで広く使われています。
真の乱数(TRNG)とは何か
真の乱数(True Random Number Generator:TRNG)は、物理的なランダム現象を利用して生成されます。
熱雑音・放射性崩壊・大気ノイズ・光子の量子状態などが乱数のソースとして利用されます。
暗号鍵の生成・ゲームのジャックポット判定・宝くじの抽選など、高いセキュリティやフェアネスが要求される場面では、擬似乱数ではなく真の乱数が使われます。
Linuxシステムでは/dev/randomや/dev/urandomというインターフェースを通じて環境ノイズ(キーボード入力・ディスクI/O・ネットワーク活動など)を収集し、高品質な乱数を提供しています。
インターネット上では「random.org」のようなサービスが大気ノイズを利用した真の乱数を提供しており、利用者は指定した範囲のランダムな整数を取得することができます。
乱数の品質を評価する方法
生成した乱数の品質を評価するためのテストとして、「TestU01」「NIST Statistical Test Suite(NIST SP800-22)」などが知られています。
これらのテストでは、乱数列が統計的に偏りなく均等に分布しているか・周期的なパターンがないか・ビット列の特性が乱数として適切かなどを多角的に検証します。
品質の低い擬似乱数を使うと、ゲームのバランスが崩れたり、モンテカルロシミュレーションの精度が落ちたり、暗号システムが解読されやすくなったりするリスクがあります。
各プログラミング言語での1〜100の乱数生成コード
続いては、各プログラミング言語での1から100のランダム値生成方法を確認していきます。
主要な言語ごとに基本的なコード例を紹介しますので、自分が使う言語のセクションを参考にしてください。
PythonとJavaScriptでの実装例
Pythonでは標準ライブラリの「random」モジュールを使うと、1行で1〜100の乱数を生成できます。
Python:1から100の乱数生成
import random
n = random.randint(1, 100) # 1以上100以下の整数
print(n)
複数の乱数をリストで生成する場合
numbers = [random.randint(1, 100) for _ in range(10)]
print(numbers)
JavaScriptでの例
const n = Math.floor(Math.random() * 100) + 1;
console.log(n);
Pythonの「random.randint(1, 100)」は1以上100以下の整数をランダムに返します。
引数の両端が含まれる点が特徴で、Python特有の仕様として覚えておきましょう。
JavaScriptの「Math.random()」は0以上1未満の浮動小数点数を返すため、100を掛けてMath.floor処理し、1を加えることで1〜100の整数に変換しています。
JavaScriptの「Math.random()」は0を含む可能性があるため、必ず1を加えて範囲を1から始めることが重要なポイントです。
また「Math.random()」は1を返さないため、Math.floor後の最大値は99となり、1を加えて最大値100になります。
JavaとC言語での実装例
JavaではRandomクラスまたはMath.randomメソッドを使用します。
Javaでの例(Randomクラス)
import java.util.Random;
Random rand = new Random();
int n = rand.nextInt(100) + 1; // 0〜99の整数に1を加えて1〜100
System.out.println(n);
C言語での例
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
srand(time(NULL)); // シードを現在時刻で初期化
int n = rand() % 100 + 1; // 0〜99に1を加えて1〜100
printf(“%d\n”, n);
return 0;
}
Javaの「rand.nextInt(100)」は0以上100未満(つまり0〜99)の整数を返すため、1を加えて1〜100の範囲にします。
C言語では「srand(time(NULL))」でシードを現在時刻で初期化してから「rand()」を呼び出すのが基本的な使い方です。
初期化を忘れると毎回同じ乱数列が生成されてしまうため、必ずsrandを先に呼び出すようにしましょう。
また「rand() % 100」の方法は厳密には均等な分布にならないことがあるため、より精度の高い乱数が必要な場合は別の方法を検討しましょう。
セキュリティが必要な場面での乱数生成
パスワードの生成・トークンの発行・暗号鍵の生成など、セキュリティが重要な場面では通常の擬似乱数ではなく暗号学的に安全な乱数(CSPRNG)を使う必要があります。
Pythonでは「secrets」モジュールの「secrets.randbelow(100) + 1」を使用することで、暗号学的に安全な1〜100の乱数が得られます。
「random」モジュールはシミュレーションやゲームには適していますが、セキュリティ用途には絶対に使ってはいけません。
JavaScriptでは「crypto.getRandomValues()」メソッドを使うことで、ブラウザ環境でも暗号学的に安全な乱数を取得できます。
Javaでは「java.security.SecureRandom」クラスがセキュリティ用途の乱数生成に使われます。
| 言語 | 1〜100乱数生成(通常) | セキュリティ用途 |
|---|---|---|
| Python | random.randint(1, 100) | secrets.randbelow(100)+1 |
| JavaScript | Math.floor(Math.random()*100)+1 | crypto.getRandomValues() |
| Java | new Random().nextInt(100)+1 | new SecureRandom().nextInt(100)+1 |
| C言語 | rand()%100+1(srand初期化必須) | OpenSSL RAND_bytes等を使用 |
| Ruby | rand(1..100) | SecureRandom.random_number(100)+1 |
乱数生成の応用と数学的な背景
続いては、乱数生成の応用例と数学的な背景について確認していきます。
乱数はゲームや統計だけでなく、科学計算・機械学習・セキュリティ・シミュレーションなどの最前線でも活用されています。
モンテカルロ法と乱数
モンテカルロ法は、大量のランダムサンプリングを用いて数値的に問題を解く手法です。
最も有名な例が円周率πの近似値を求める方法で、1×1の正方形の内側にランダムに点を打ち、内接する円の内部に入る点の割合からπを推定します。
円の内部に入る確率はπ/4であるため、大量に点を打って割合を求めると4倍することでπの近似値が得られます。
乱数の品質が高いほどモンテカルロ法の収束が速くなり精度が上がるため、シミュレーション科学では乱数の品質管理が非常に重要です。
金融工学でのオプション価格計算・核物理シミュレーション・気候モデルの計算など、モンテカルロ法は現代科学の多くの場面で使われています。
ゲーム開発での乱数活用
ゲーム開発において乱数は欠かせない存在です。
敵キャラクターの行動パターン・アイテムのドロップ確率・ダメージのばらつき・マップの自動生成(プロシージャル生成)・カードゲームのシャッフル・ガチャシステムなど、乱数が使われる場面は数え切れないほどあります。
ゲームバランスを保つためには偏りのない高品質な乱数が必要であり、「引きが悪い」「特定の結果ばかり出る」という問題は乱数の品質や実装の問題に起因することがあります。
シード値の管理によってリプレイ機能(同じプレイを完全に再現する機能)を実現しているゲームも多く、「シード値を共有するだけで友人と同じ体験を共有できる」という設計は近年のゲームでも見られます。
統計・機械学習での利用
統計学や機械学習の分野では、データのシャッフル・訓練データとテストデータへの分割・初期パラメーターのランダム設定・ドロップアウト処理・データ拡張(ランダムな変形・回転・クロッピング)などに乱数が使われます。
機械学習モデルの学習において再現性を確保するため、シード値を固定するという操作は非常に一般的なプラクティスです。
Pythonの機械学習ライブラリ「scikit-learn」では「random_state」パラメーター、「TensorFlow」や「PyTorch」では「tf.random.set_seed()」や「torch.manual_seed()」という形でシードを固定できます。
論文の再現性を確保するためにシード値を公開することは、現代の機械学習研究における重要な慣行となっています。
乱数に関する数学的な深掘り
続いては、乱数生成に関する数学的な背景をさらに深く確認していきます。
ここでは乱数の性質・分布・テストについて解説します。
一様分布乱数と非一様分布乱数
通常のプログラムで生成される乱数は「一様分布(uniform distribution)」に従い、各値が等しい確率で出現します。
しかし実際のシミュレーションや統計処理では、正規分布(ガウス分布)・ポワソン分布・指数分布など、特定の分布に従う乱数が必要な場合もあります。
一様分布乱数から正規分布乱数を生成する方法としては「ボックス・ミュラー法」が有名で、Pythonのnumpyライブラリなどで実装されています。
分布の変換を理解しておくと、統計シミュレーションや機械学習の実装に大きく役立つでしょう。
乱数の偏り問題と対策
乱数生成において「偏り(bias)」は大きな問題のひとつです。
特定の数が他の数より多く出現したり、特定のパターンが繰り返されたりすると、シミュレーションやゲームの公平性が損なわれます。
剰余演算(rand() % 100)を使うだけでは、乱数の分布が均等にならないケースがあります(modulo biasと呼ばれる問題)。
これを防ぐためには、使わない範囲の値を棄却するrejection samplingという手法が使われます。
乱数とセキュリティの関係
暗号セキュリティにおける乱数の重要性は非常に高く、乱数の予測可能性が暗号システム全体の脆弱性につながることがあります。
過去には、ゲームやロトシステムで使われていた乱数の実装が解析され、次の乱数が予測されたという事例があります。
セキュリティ用途では必ず暗号学的に安全な乱数生成器(CSPRNG)を使い、定期的に最新のライブラリやアルゴリズムにアップデートすることが大切です。
| 応用分野 | 乱数の使われ方 | 必要な品質レベル | 推奨アルゴリズム |
|---|---|---|---|
| ゲーム開発 | ドロップ確率・行動AI | 中程度 | Mersenne Twister |
| 統計シミュレーション | モンテカルロ法・サンプリング | 高品質 | Mersenne Twister・xorshift |
| 機械学習 | 初期化・シャッフル・ドロップアウト | 中〜高品質 | 各フレームワークの標準 |
| 暗号・セキュリティ | 鍵生成・トークン発行 | 最高品質(予測不可能) | CSPRNG・/dev/urandom |
まとめ
本記事では、乱数生成の基本的な仕組み・擬似乱数と真の乱数の違い・各言語での1〜100乱数生成コード・応用例・数学的背景について幅広く解説しました。
1から100のランダム値を生成するには、各言語の標準ライブラリに用意された乱数関数を使うのが最も手軽で確実な方法です。
通常のシミュレーションやゲームには擬似乱数(Mersenne Twisterなど)で十分ですが、セキュリティ用途には暗号学的に安全な乱数生成器(CSPRNG)を使わなければなりません。
シード値の管理・乱数の品質・用途に応じた乱数の選択という3つのポイントを押さえておくと、プログラムの信頼性と品質が大きく向上するでしょう。
モンテカルロ法・ゲーム開発・機械学習など、乱数が活躍する分野は非常に広く、その重要性は今後も増していくはずです。
乱数生成はプログラミングの基本スキルのひとつですので、ぜひ今回の内容を参考に実際のコードで試し、理解を深めてみてください。