高品質乱数生成
Web

High Quality Random RandInt

Web Cryptoの乱数を、指定した整数範囲へ偏りなく写す。
BigIntと棄却法で実装したブラウザツールです。

← Apps 一覧へ戻る

Overview

High Quality Random RandInt は、最小値と最大値を指定して整数を生成するWebアプリです。抽選、順番決め、テストデータ作成などに使えるよう、処理はブラウザ内で完結します。

実装で重視したのは、Math.random() の値へ単純な掛け算をするのではなく、Web Crypto APIの crypto.getRandomValues() を乱数源にし、任意の大きさの整数範囲へ偏りなく変換することです。

Features

  • 最小値・最大値を含む整数範囲から生成
  • crypto.getRandomValues() を乱数源として使用
  • BigInt により大きな整数範囲を扱う
  • 棄却法で剰余による偏りを除く
  • 入力と計算はブラウザ内で完結

単純な剰余では、結果が偏る

例えば0〜255の一様な1バイト値を、そのまま value % 10 で0〜9へ変換するとします。256は10で割り切れないため、余り0〜5は26通り、6〜9は25通りから発生します。元の乱数が一様でも、変換後は一様ではありません。

範囲が小さい場合は差が目立たなくても、抽選回数を増やすと偏りは積み重なります。この「modulo bias」を避けるため、使ってよい元の値の上限を先に決め、端数部分を捨てます。

BigIntと棄却法による生成手順

利用者が指定した最小値を min、最大値を max とすると、結果の個数は次の値です。

range = max - min + 1

range を表せるだけのバイト数 n を求め、Web Crypto APIで n バイトを生成します。その全パターン数を 2^(8n) としたとき、range で割り切れる最大の境界を計算します。

sourceSize = 2 ** (8 * n)
maxValid  = sourceSize - (sourceSize % range)

do {
  value = crypto.getRandomValues(n bytes) → BigInt
} while (value >= maxValid)

result = min + (value % range)

maxValid 以上の値は使わず、もう一度生成します。残ったパターン数は必ず range の倍数なので、どの結果にも同じ数の元パターンが対応します。

計算を Number ではなく BigInt で行うのは、大きな整数で浮動小数点の丸めが入らないようにするためです。入力の大小関係と範囲を検証し、必要なバイト数を範囲に合わせて増やします。

棄却はどのくらい発生するか

必要な範囲を表せる最小のバイト数を使うと、棄却されるのは末尾の端数だけです。1回で採用されない可能性はありますが、採用されるまで同じ手順を繰り返すことで分布を保ちます。

この方法は「生成後に結果を補正する」のではなく、初めから各結果へ同数の入力を割り当てる方法です。UIには結果だけを表示しますが、別ページにアルゴリズムの説明を用意し、ツール名の「高品質」が何を指すのか確認できるようにしています。

用途と限界

crypto.getRandomValues() は暗号学的に強い乱数値を得るためのブラウザAPIですが、このWebツール全体が暗号製品として監査済みという意味ではありません。

  • 日常の抽選、順番決め、テスト値、ゲーム試作を想定
  • 結果をサーバーへ送信・保存する処理は使用しない
  • ブラウザや端末の乱数実装と実行環境に依存する
  • 第三者が検証できる抽選履歴やコミット・リビール方式は備えない
  • 暗号鍵、認証トークン、復旧コードの生成には用途専用の実装を使う

「乱数源がWeb Cryptoであること」「範囲変換に剰余の偏りを入れないこと」は実装上の性質です。一方、公正な抽選の運用、改ざん防止、監査可能性は別の問題として扱う必要があります。

App Info

Platform
Web
Language
JavaScript
Developer
okojo