【JavaScript】乱数を生成する方法

JavaScriptで乱数を作る基本は Math.random() です。ただし用途によっては Math.random() を使ってはいけない場面があります。この記事では、一般的な乱数の作り方から、配列のシャッフル、安全な乱数が必要なケースまでを解説します。

この記事の結論:一般用途は Math.random() をスケーリングして使います(整数は Math.floor(Math.random() * (max - min + 1)) + min)。ただしパスワード・トークン・抽選などセキュリティや公平性が必要な乱数に Math.random() は使えません。その場合は crypto.getRandomValues()crypto.randomUUID() を使います。
スポンサーリンク

0以上1未満の乱数(Math.random)

Math.random()0以上1未満0 は含むが 1 は含まない)のランダムな小数を返します。これを基準に、欲しい範囲へ変換していきます。

JavaScript:0以上1未満
const r = Math.random();
console.log(r); // 例: 0.4729... (0 <= r < 1)

任意範囲の整数・小数を生成する

整数は、範囲の幅を掛けて Math.floor() で切り捨て、最小値を足します。(max - min + 1) とすることで最大値も含めます

JavaScript:範囲指定の整数(min〜maxを含む)
function randomInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

console.log(randomInt(1, 100)); // 1〜100 のいずれか
console.log(randomInt(1, 6));   // サイコロ(1〜6)

小数(浮動小数点数)は Math.floor() を使わず、幅を掛けて最小値を足すだけです。こちらは max を含みませんmin 以上 max 未満)。

JavaScript:範囲指定の小数
function randomFloat(min, max) {
  return Math.random() * (max - min) + min;
}

console.log(randomFloat(5, 10)); // 例: 7.23... (5 <= x < 10)

Math や小数計算の基本は四則演算と計算の基本にまとめています(小数計算の誤差にも注意)。

配列からランダムに選ぶ・シャッフルする

配列から1つランダムに取り出すには、ランダムなインデックスを作ります。

JavaScript:配列からランダムに1つ
const items = ["りんご", "みかん", "ぶどう"];
const picked = items[Math.floor(Math.random() * items.length)];
console.log(picked); // いずれか1つ

配列全体をシャッフルするなら、Fisher-Yates(フィッシャー・イェーツ)アルゴリズムを使います。後ろから順に、ランダムな位置と交換していく方法で、偏りなく並び替えられます。

JavaScript:Fisher-Yatesでシャッフル
function shuffle(array) {
  const a = [...array]; // 元の配列を壊さないようコピー
  for (let i = a.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [a[i], a[j]] = [a[j], a[i]]; // 交換
  }
  return a;
}

console.log(shuffle([1, 2, 3, 4, 5]));
よくある間違い:array.sort(() => Math.random() - 0.5) は手軽ですが、並びに偏りが出る(各要素が均等に散らばらない)ため、シャッフルには向きません。公平さが必要なら Fisher-Yates を使ってください。

セキュリティ用途は Math.random を使わない

最重要:Math.random()予測可能で、暗号学的に安全ではありません。パスワード・トークン・セッションID・抽選など推測されると困る乱数には使わないでください。その場合は crypto を使います。

IDやトークンには crypto.randomUUID() が手軽で安全です(モダンブラウザ・Node.js対応)。

JavaScript:安全なランダムID
const id = crypto.randomUUID();
console.log(id); // 例: "54ee4515-980c-40d4-8414-a4f9ab226b4a"

安全な「整数」が必要なときは crypto.getRandomValues() を使います。ただし単純に剰余(%)を取るとわずかな偏り(modulo bias)が出るため、範囲外の値を捨てて取り直します。

JavaScript:安全な範囲指定の整数
function secureRandomInt(min, max) {
  const range = max - min + 1;
  // 偏りを防ぐため、割り切れる最大値を求めて範囲外は捨てる
  const maxValid = Math.floor(0xFFFFFFFF / range) * range;
  const buf = new Uint32Array(1);
  let x;
  do {
    crypto.getRandomValues(buf);
    x = buf[0];
  } while (x >= maxValid);
  return min + (x % range);
}

console.log(secureRandomInt(1, 6)); // 安全なサイコロ

ランダムな文字列(パスワード・トークン)の安全な作り方は指定した文字数のランダムな文字列を生成する方法で、Math.randomcrypto の使い分けを含めて詳しく解説しています。

よくある質問(FAQ)

QJavaScriptでランダムな整数を生成するには?
AMath.floor(Math.random() * (max - min + 1)) + min で指定範囲の整数が得られます。例:1〜6のサイコロは Math.floor(Math.random() * 6) + 1 です。
QMath.random() はパスワードやトークンに使えますか?
Aいいえ。Math.random()予測可能で暗号学的に安全ではないため、パスワード・トークン・抽選などには使えません。crypto.randomUUID()crypto.getRandomValues() を使ってください。
Q配列をランダムにシャッフルするには?
AFisher-Yatesアルゴリズムを使います。array.sort(() => Math.random() - 0.5) は実装が簡単ですが分布が偏るため、公平さが必要な場合は Fisher-Yates を使ってください。
QランダムなIDや識別子を生成するには?
Acrypto.randomUUID() でUUID v4形式の安全なIDが生成できます(モダンブラウザ・Node.js対応)。簡易的な用途なら Math.random().toString(36).slice(2) でも英数字のランダム文字列を作れます。

まとめ

一般的な乱数は Math.random() をスケーリングして作ります。整数は Math.floor(Math.random() * (max - min + 1)) + min、小数は Math.random() * (max - min) + min が基本です。シャッフルは Fisher-Yates を使いましょう。

最も大切なのは、パスワードやトークンなどのセキュリティ用途に Math.random() を使わないことです。そうした場面では crypto.randomUUID()crypto.getRandomValues()(modulo bias に注意)を使い、安全な乱数を生成してください。