- 技術 💻
乱数生成ツール|範囲・個数・重複なしで作る方法とプログラムでの作り方
結論
乱数生成は、下のツールに「最小・最大・個数」を入れてボタンを押すと、その場でできます。重複なし・小数・並べ替え・リストのシャッフルにも対応し、シードを入れると同じ結果をもう一度出せます。
この記事でわかること
- 範囲・個数・重複なしで乱数を作る手順と、結果の読み方
- Python・JavaScript・Java・SQL・シェルで乱数を作った実行結果
- % の余りで出る偏りと、サイコロ6万回をカイ二乗で確かめた数字
乱数生成ツールを読み込み中です。
ツールの使い方:上の切り替えで「数を作る」か「リストから選ぶ・並べ替える」を選び、条件を入れてボタンを押します。作った数はこの端末の中だけで計算し、どこにも送信しません。
- 数を作る:最小・最大・個数(1〜10,000)を入れて「乱数を作る」を押します。整数か小数(第1〜3位まで)、並べ方(出た順・小さい順・大きい順)、区切り(改行・カンマ・空白・タブ)を選べます。同じ数を出したくないときは「重複なし」、桁数をそろえたいときは「桁をそろえる(0埋め)」にチェックを入れます。
- 見本のボタン:「サイコロ(1〜6)」「コイン(0か1)」「1〜100を1つ」「1〜100を10個」「くじ(1〜43から重複なしで6個)」「4桁の数字」「0〜1の小数」を押すと、条件が入ってそのまま結果が出ます。
- リストから選ぶ・並べ替える:1行に1つずつ書いたリストをシャッフルします。「選ぶ数」を空にすると全部を並べ替え、数を入れるとその数だけ取り出します。発表の順番や担当決めに使えます。
- シード(任意):好きな文字や数を入れると、同じシード・同じ設定のときは同じ結果になります。空のままなら毎回違う結果です。
- 結果の下の表:個数、範囲の中の数が何通りあるか、合計・平均、最小・最大、範囲の真ん中、使った乱数の種類が出ます。「結果をコピー」でそのまま貼り付けられます。
このツールは、パスワードや鍵を作る用途のものではありません。数の抽選・並べ替え・テスト用の値づくりに使う道具です。
この記事で実際に動かしたもの:記事内の乱数生成ツール(Chromium で操作)と、Python・Node.js・Java・SQLite・PostgreSQL・bash・shuf の乱数の実行結果、余りの偏りとカイ二乗の計算です。
プログラムの乱数は、ほとんどが「シード(出発点の数)から、決まった計算で次々に作る」仕組みです。全体の流れを先に図で示します。
flowchart TD
O[OSの乱数源<br>予測しにくい値] -.->|シードが空のとき| S[シード<br>出発点の数]
S --> G[疑似乱数生成器<br>決まった計算]
G --> N[乱数の列<br>同じシードなら同じ並び]
N --> R[範囲に合わせる<br>1〜6 など]
よく調べられることの答えを先にまとめます。
| 知りたいこと | 答え | 詳しい節 |
|---|---|---|
| 乱数生成をすぐしたい | 上のツールに最小・最大・個数を入れて押す | 乱数生成ツールでできること |
| 乱数生成 重複なし | 「重複なし」にチェック。プログラムではシャッフルして先頭から取る | 重複なしの乱数の作り方 |
| 乱数生成 範囲指定 | 端を含むかは関数ごとに違う。Python の randint は両端を含む | 範囲指定でよくある間違い |
| 乱数生成 Python | random.randint(1, 6)。秘密の値は secrets |
Python の乱数生成 |
| 乱数生成 JavaScript | Math.floor(Math.random() * 6) + 1 |
JavaScript の乱数生成 |
| 乱数生成 Java | new Random().nextInt(6) + 1 |
Java の乱数生成 |
| 疑似乱数とは | 計算で作る、乱数のように見える数の列 | 乱数とは |
| シードとは | 疑似乱数の出発点。同じシードなら同じ並びになる | シードとは |
| 偏りがないか確かめたい | たくさん出して数え、カイ二乗の値を計算する | 乱数に偏りがないかの確かめ方 |
確認環境:Ubuntu 24.04.5 LTS の上で、Python 3.13.18(random・secrets・SciPy 1.18.1)、Node.js 22.23.4(Math.random・node:crypto)、OpenJDK 21.0.12(java.util.Random・ThreadLocalRandom・SecureRandom)、SQLite 3.53.1(Python の sqlite3 から)、PostgreSQL 16.15(127.0.0.1 に一時的に起動し、確認後に停止・削除)、GNU bash 5.2.21、GNU coreutils 9.4 の shuf を実行し、出力をそのまま載せています。乱数の出力は実行のたびに変わるため、シードを指定していない例の値は一例です。記事内のツールは、テーマの JavaScript と CSS を 127.0.0.1 で配信したページを Chromium 153.0.8010.12(Playwright 1.63.0・幅390px)で開き、見本ボタン・シード・重複なし・エラー表示・リストの並べ替えを操作して確かめました。各関数の範囲や注意書きは、Python・MDN・Oracle(Java SE 21)・SQLite・PostgreSQL 16・GNU の公式ドキュメントで確かめています。図は mermaid 11.16.0 で描画を確かめました(確認日 2026年11月11日)。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「乱数生成ツール|範囲・個数・重複なしで作る方法とプログラムでの作り方」
乱数とは(疑似乱数と真の乱数の違い)
この節では、乱数という言葉の意味と、コンピューターが作る「疑似乱数」と物理現象から作る「真の乱数」の違いが分かります。
乱数とは、次に何が出るか分からず、どの値も同じ割合で出る数の並びのことです。サイコロを振って出る 1〜6 の目が身近な例です。プログラムでは、抽選・並べ替え・テスト用の値・シミュレーション・ゲームの演出などに使います。
コンピューターは決まった手順どおりに動く機械なので、そのままでは「でたらめな数」を作れません。そこで、次の2通りの作り方があります。
疑似乱数(計算で作る)
出発点の数(シード)から計算で次々に作る
同じシードなら、同じ並びをもう一度出せる
速い。Python の random、Math.random、Java の Random など
真の乱数(物理現象から作る)
電気的な雑音など、予測できない現象を測って作る
同じ並びをもう一度出すことはできない
OS が集めた値は、暗号用の乱数のシードに使われる
計算で作る様子を小さな例で見る
疑似乱数の中身は、掛け算・足し算・余りなどの計算です。仕組みが見えるように、とても小さな式 次の数 = (5 × 今の数 + 3) を 16 で割った余り で、シード 7 から20個作りました。
def small(seed):
x = seed
while True:
x = (5 * x + 3) % 16
yield x
g = small(7)
print([next(g) for _ in range(20)])
[6, 1, 8, 11, 10, 5, 12, 15, 14, 9, 0, 3, 2, 13, 4, 7, 6, 1, 8, 11]
0〜15 がばらばらの順に1回ずつ出て、17個目から最初と同じ並び(6, 1, 8, 11…)に戻りました。この「一巡して元に戻るまでの長さ」を周期と呼びます。この例の周期は16です。実際に使われる生成器は周期がとても長く、Python の公式ドキュメントは、標準の生成器(メルセンヌツイスタ)の周期を 2 の 19937 乗 − 1 と説明しています。10進数で書くと 6,002 桁になる数です。
暗号用の乱数という第3の種類
疑似乱数の中には、出力を見ても次の値を予測しにくいように作られた暗号用の乱数(暗号論的疑似乱数)があります。ブラウザの crypto.getRandomValues() について、MDN は「真の乱数発生器を使用しているのではないものの、十分なエントロピーを有するシード値を用いた擬似乱数発生器を使用している」と説明しています。エントロピーとは、ここでは予測のしにくさの量のことです。
| 種類 | 作り方 | 再現 | 代表例 |
|---|---|---|---|
| 疑似乱数 | シードから計算 | できる | Python random、Math.random、Java Random、PostgreSQL random() |
| 暗号用の乱数 | OS の乱数源をシードにした、予測しにくい計算 | できない | Python secrets、crypto.getRandomValues、Java SecureRandom |
| 真の乱数 | 物理現象を測る | できない | 専用の機器、OS が集める雑音 |
ふだんのプログラムで「乱数」と呼んでいるものは、ほぼ疑似乱数です。分布の種類(一様・正規など)については、関連記事「確率分布とは|種類一覧・平均と分散・選び方をPythonで実演」で扱っています。この記事で作るのは、どの値も同じ割合で出る「一様乱数」です。
シードとは(同じシードで同じ乱数になる仕組みと使い道)
この節では、シードの意味と、シードを固定して同じ乱数をもう一度出す使い道が分かります。
シード(seed、種)は、疑似乱数の計算の出発点になる値です。同じシードから始めると、同じ並びの乱数が出ます。Python で確かめます。
import random
random.seed(42)
print(random.random())
random.seed(42)
print(random.random())
0.6394267984578837
0.6394267984578837
シードを指定しないときは、実行のたびに違う値で始まります。Python の公式ドキュメントは、シードを省略した場合について、OS が乱数源を提供していればそれを使い、無ければ現在のシステム時刻を使うと説明しています。
シードを固定する使い道
1テストデータを毎回同じにする
乱数で作ったデータでも、シードが同じなら毎回同じ中身になる。テストの結果を前回と比べやすい。
2不具合を再現する
乱数を使う処理で失敗したとき、そのときのシードをログに残しておくと、同じ並びでもう一度動かせる。
3結果を確かめ直せるようにする
シミュレーションや並べ替えの結果を、シードと条件を添えて共有すると、ほかの人が同じ結果を出して確かめられる。
シード 2026 でテスト用の行を5つ作った例です。何度実行しても同じ行になりました。
import random
random.seed(2026)
for i in range(1, 6):
print((i, random.choice(["東京", "大阪", "福岡"]),
random.randint(100, 9999), round(random.uniform(0, 1), 3)))
(1, '東京', 5334, 0.503)
(2, '福岡', 1781, 0.884)
(3, '福岡', 9218, 0.421)
(4, '福岡', 9075, 0.842)
(5, '大阪', 9709, 0.441)
注意点は2つあります。1つ目は、同じシードで同じ結果になるのは、同じ言語・同じ関数・同じ呼び出し順のときだけという点です。シード 42 でも、Python と Java では別の並びになります。2つ目は、シードを固定した乱数は予測できるので、人に知られて困る値(鍵やトークン)には使えないという点です。テストデータ全体の作り方は、関連記事「テストデータの作り方|生成SQLとマスキング手法一覧・匿名化の手順」で扱っています。
乱数生成ツールでできることと結果の読み方
この節では、記事の先頭にある乱数生成ツールを実際に操作した結果と、表示の読み方、エラー表示の意味が分かります。
ツールは、シードが空のときはブラウザの暗号用の乱数(crypto.getRandomValues)を使い、シードを入れたときはシードから計算する乱数に切り替わります。どちらで作ったかは、結果の下の表の「乱数の種類」に出ます。
見本ボタンを押した結果
Chromium でそれぞれのボタンを押し、入る条件と出た結果を確かめました(シードは空。結果は一例です)。
| 見本ボタン | 入る条件 | 出た結果の例 | 範囲の中の数 |
|---|---|---|---|
| サイコロ(1〜6) | 1〜6 を1個 | 3 | 6 通り |
| コイン(0か1) | 0〜1 を1個 | 0 | 2 通り |
| 1〜100を1つ | 1〜100 を1個 | 93 | 100 通り |
| 1〜100を10個 | 1〜100 を10個(重複あり) | 46 85 29 97 86 96 22 67 92 62 | 100 通り |
| くじ(1〜43から重複なしで6個) | 1〜43 を6個・重複なし・小さい順 | 8 20 26 36 37 43 | 43 通り |
| 4桁の数字 | 0〜9999 を1個・0埋め | 2093 | 10,000 通り |
| 0〜1の小数 | 0〜1 を5個・小数第3位まで | 0.910 0.734 0.508 0.566 0.955 | 1,001 通り |
「0〜1の小数」の範囲の中の数が 1,001 通りなのは、0.000 から 1.000 までを 0.001 刻みで数え、両端を含めているためです。プログラムの random() は 1.0 を含まないことが多いので、この点は違います(後の節で扱います)。
シードを入れて同じ結果になることを確かめる
最小 1・最大 100・個数 10・整数・出た順のまま、シードに 2026 と入れて「乱数を作る」を2回押したところ、2回とも次の結果でした。
41 92 95 41 43 50 39 42 59 80
「乱数の種類」は「シードから作る乱数(同じシードなら同じ結果)」に変わり、合計・平均は 582・58.2、最小・最大は 39・95 と出ました。シードを 2027 に変えると 99 36 77 19 20 48 86 77 52 35 と別の並びになりました。どちらの結果にも同じ数(41、77)が2回出ています。重複ありの乱数では、これは珍しいことではありません(確率は後の節で計算します)。
結果の下の表の読み方
- 個数(範囲の中の数は◯通り):作った個数と、その範囲に入る数が何種類あるか。重複なしで作れる上限でもあります。
- 合計・平均、最小・最大:出た数を集計した値。
- 範囲の真ん中:最小と最大の中間の値(1〜100 なら 50.5)。個数が多いほど、平均はこの値に近づきます。−5〜5 を10,000個作ったときは、平均 0.023 でした。
- 乱数の種類:ブラウザの暗号用の乱数か、シードから作る乱数か。
並べ方・区切り・0埋め・小数
1〜100 を5個、小さい順・カンマで区切る・0埋めにすると 009, 031, 055, 065, 073 のように、最大値の桁数(3桁)にそろいます。同じ条件で「小数第2位まで」にすると 9.90, 30.76, 55.20, 64.73, 72.43 のように小数で出て、範囲の中の数は 9,901 通りと表示されました(1.00〜100.00 を 0.01 刻みで数えた数です)。
リストから選ぶ・並べ替える
はじめから入っている5行(Aチーム〜Eチーム)を並べ替えると、1. Bチーム〜5. Cチーム のように番号つきで出ます。表には「リストの数 5 個」「並べ方の総数 120 通り」と出ました。5個の並べ方は 5×4×3×2×1 = 120 通りだからです。並べ方の総数は、リストが20個までのときに表示されます。「選ぶ数」に 2 を入れると、並べ替えた結果の先頭2つだけが出ます。
ツールのエラー表示
| 表示(原文) | 出る条件 | 直し方 |
|---|---|---|
| 重複なしで作れるのは 6 個までです(範囲の中の数が 6 個のため)。 | 1〜6 から重複なしで7個など、個数が範囲の中の数を超えた | 個数を減らすか、範囲を広げるか、重複なしを外す |
| 個数は1〜10,000で入れます。 | 個数が 0 や 10,001 など | 1〜10,000 にする。それ以上はプログラムで作る |
| 最小と最大に数を入れます。 | 最小・最大が空か、数として読めない | 数字を入れる |
| この範囲には、整数がありません。 | 0.5〜0.6 を整数で作ろうとした | 範囲を広げるか、小数に切り替える |
| 選ぶ数(9)がリストの数(5)より多くなっています。 | リスト5行から9個を選ぼうとした | 選ぶ数を減らすか、リストを足す |
Python の乱数生成(random と secrets)
この節では、Python で乱数を作る基本の関数と、実行した出力、random と secrets の使い分けが分かります。
Python では、ふつうの乱数は random モジュール、人に知られて困る値は secrets モジュールで作ります。シード 42 で実行した結果です。
import random, secrets
random.seed(42)
print(random.random()) # 0.0 以上 1.0 未満の小数
print([random.randint(1, 6) for _ in range(10)]) # 1〜6(両端を含む)
print([random.randrange(1, 6) for _ in range(10)]) # 1〜5(6 は含まない)
print(random.choice(["A", "B", "C", "D", "E"])) # 1つ選ぶ
print(sorted(random.sample(range(1, 44), 6))) # 重複なしで6個
a = list(range(1, 11)); random.shuffle(a); print(a) # 並べ替える
print([secrets.randbelow(6) + 1 for _ in range(10)]) # 暗号用の乱数で 1〜6
0.6394267984578837
[1, 6, 3, 2, 2, 2, 6, 1, 6, 6]
[5, 1, 5, 4, 1, 1, 1, 2, 2, 5]
E
[13, 15, 27, 29, 35, 42]
[9, 8, 6, 3, 4, 2, 7, 1, 5, 10]
[4, 6, 6, 5, 5, 2, 6, 6, 3, 5]
最後の行(secrets)だけは、シードの影響を受けず毎回変わります。
| 関数 | 返す値 | 端の扱い |
|---|---|---|
random.random() |
小数 | 0.0 以上 1.0 未満 |
random.randint(a, b) |
整数 | a も b も含む |
random.randrange(a, b) |
整数 | a は含み、b は含まない |
random.uniform(a, b) |
小数 | b を含むかは丸めしだい(公式の注記) |
random.sample(母集団, k) |
重複なしの k 個 | k が母集団より多いとエラー |
secrets.randbelow(n) |
整数(暗号用) | 0 以上 n 未満 |
Python の公式ドキュメントは random モジュールの冒頭で、この疑似乱数生成器をセキュリティ目的に使わないこと、その用途には secrets モジュールを見ることを警告しています。関数の一覧と細かな使い方は、関連記事「Python randomの使い方一覧|randint・choice・shuffle」で扱っています。
JavaScript の乱数生成(Math.random と crypto)
この節では、JavaScript で範囲を指定して乱数を作る式と、Math.random と crypto の違いが分かります。
JavaScript の Math.random() は、0 以上 1 未満の小数を返します。整数にするには、掛け算と切り捨てを組み合わせます。
// min 以上 max 以下の整数(両端を含む)
const randInt = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
console.log(Math.random());
console.log(Array.from({ length: 10 }, () => randInt(1, 6)).join(' '));
// 暗号用の乱数
const u = new Uint32Array(3);
crypto.getRandomValues(u);
console.log(Array.from(u).join(' '));
0.7692676541259453
5 3 5 1 6 2 5 6 6 3
142659048 2453667508 87628585
MDN は Math.random() について、次の2点を説明しています。
- シードは選べない:初期シードは実装側が選び、利用者が選んだりリセットしたりはできません。同じ並びを再現したいときは、シードつきの生成器を自分で用意します。
- 暗号には使えない:セキュリティに関わる目的では使わず、代わりに
crypto.getRandomValues()を使うよう案内しています。
シードつきの小さな生成器(mulberry32 と呼ばれる式)で、同じシードから同じ並びが出ることを確かめました。
function mulberry32(a) {
return function () {
a = (a + 0x6D2B79F5) | 0;
let t = Math.imul(a ^ (a >>> 15), 1 | a);
t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
};
}
let r = mulberry32(42);
console.log(Array.from({ length: 5 }, () => Math.floor(r() * 100) + 1).join(' '));
r = mulberry32(42);
console.log(Array.from({ length: 5 }, () => Math.floor(r() * 100) + 1).join(' '));
61 45 86 67 18
61 45 86 67 18
Node.js では crypto.randomInt(1, 7)(node:crypto)で、1 以上 7 未満の整数を暗号用の乱数から直接作れます。実行すると 1 6 6 5 1 4 6 1 3 5 のように出ました。
Java の乱数生成(Random・ThreadLocalRandom・SecureRandom)
この節では、Java の3つの乱数クラスの使い方と実行結果、使い分けが分かります。
Java では、シードで再現したいときは Random、複数スレッドで使うときは ThreadLocalRandom、秘密の値には SecureRandom を使います。
import java.security.SecureRandom;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.*;
public class Rng {
public static void main(String[] args) {
Random r = new Random(42);
System.out.println(IntStream.range(0, 10).map(i -> r.nextInt(6) + 1).boxed().toList());
Random r2 = new Random(42);
System.out.println(IntStream.range(0, 10).map(i -> r2.nextInt(6) + 1).boxed().toList());
System.out.println(IntStream.range(0, 10).map(i -> r.nextInt(1, 7)).boxed().toList());
System.out.println(IntStream.range(0, 10)
.map(i -> ThreadLocalRandom.current().nextInt(1, 7)).boxed().toList());
SecureRandom s = new SecureRandom();
System.out.println(IntStream.range(0, 10).map(i -> s.nextInt(6) + 1).boxed().toList());
List<Integer> list = IntStream.rangeClosed(1, 43).boxed().collect(Collectors.toList());
Collections.shuffle(list, new Random(42));
System.out.println(list.subList(0, 6));
}
}
[3, 4, 1, 3, 1, 2, 6, 3, 2, 6]
[3, 4, 1, 3, 1, 2, 6, 3, 2, 6]
[3, 3, 1, 1, 3, 3, 1, 1, 2, 6]
[5, 4, 4, 3, 2, 2, 3, 4, 6, 2]
[4, 2, 4, 2, 3, 6, 3, 3, 2, 3]
[33, 40, 23, 27, 4, 11]
1行目と2行目は、同じシード 42 なので同じ並びです。nextInt(6) は 0 以上 6 未満(0〜5)を返すので、1〜6 にするには 1 を足します。nextInt(1, 7) は 1 以上 7 未満です。
| クラス | シードの指定 | 向く用途 |
|---|---|---|
java.util.Random |
できる(new Random(42)) |
テストデータ・シミュレーション・再現したい処理 |
ThreadLocalRandom |
できない(setSeed は UnsupportedOperationException) | 複数スレッドから乱数を使う処理 |
SecureRandom |
再現の用途には使わない | トークンなど、予測されて困る値 |
Oracle の API ドキュメントは、java.util.Random のインスタンスは暗号論的に安全ではないこと、セキュリティに関わる用途では SecureRandom を、マルチスレッドの設計では ThreadLocalRandom を検討することを案内しています。Java の乱数だけを詳しく知りたいときは、関連記事「Java乱数の作り方|Random nextIntの範囲指定と使い分け」で扱っています。
SQL とシェルの乱数生成(RANDOM()・$RANDOM・shuf)
この節では、SQLite・PostgreSQL の乱数の関数と、bash の $RANDOM、shuf コマンドの使い方が実行結果つきで分かります。
SQL の乱数は、データベースごとに返す値の形が違います。SQLite の random() は大きな整数、PostgreSQL の random() は 0.0 以上 1.0 未満の小数です。
SQLite
SELECT random(); -- -7966765089160609884
SELECT abs(random()) % 6 + 1; -- 3
SELECT id, name FROM member ORDER BY random() LIMIT 3;
-- (8, 'member08'), (7, 'member07'), (6, 'member06')
SQLite の公式ドキュメントによると、random() は −9223372036854775807 から +9223372036854775807 までの整数を返します。ORDER BY random() LIMIT 3 は、10行の表から重複なしで3行を選ぶ書き方です。
PostgreSQL
SELECT random(); -- 0.9445709073631825
SELECT floor(random() * 6)::int + 1 AS dice; -- 2
SELECT setseed(0.42);
SELECT floor(random() * 100)::int + 1 AS n FROM generate_series(1, 5);
-- 75, 37, 94, 7, 10(setseed(0.42) をやり直すと同じ5つ)
SELECT n FROM generate_series(1, 43) AS n ORDER BY random() LIMIT 6;
-- 26, 21, 41, 9, 4, 12
setseed() に −1.0〜1.0 の値を渡すと、同じセッションの中で同じ並びを再現できます。PostgreSQL 16 で SELECT random(1, 6); と書くと、次のエラーになりました。16 の random() は引数を取りません。
ERROR: function random(integer, integer) does not exist
LINE 1: SELECT random(1, 6);
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
PostgreSQL の公式ドキュメントは、random() は決まった計算で作る疑似乱数で、速いが暗号の用途には向かないと説明しています。
bash の $RANDOM と shuf
echo "$RANDOM $RANDOM $RANDOM" # 0〜32767 の整数
RANDOM=42; echo "$RANDOM $RANDOM $RANDOM" # 代入するとシードになる
RANDOM=42; echo "$RANDOM $RANDOM $RANDOM"
echo $((RANDOM % 6 + 1)) # 1〜6
shuf -i 1-100 -n 5 # 1〜100 から重複なしで5個
shuf -i 1-6 -n 10 -r # 1〜6 から重複ありで10個
printf 'A\nB\nC\nD\nE\n' | shuf # 行を並べ替える
shuf -i 1-5 -n 6 # 5個しか無いところから6個
17095 25555 1917
17772 26794 1435
17772 26794 1435
5
54 77 86 98 69
4 2 6 2 4 5 2 5 1 2
C B D A E
4 3 2 1 5
(shuf の出力は1行に1つですが、ここでは横に並べています。)shuf は重複なしが既定で、-r を付けると重複ありになります。最後の例のように、候補より多い個数を指定してもエラーにはならず、ある分(5個)だけが出ました。GNU のマニュアルは -n を「多くても count 行を出力する」と説明しています。
範囲指定でよくある間違い(端を含む・含まない)
この節では、乱数の範囲を指定するときに起きやすい間違いと、実際に数えた結果が分かります。
いちばん多い間違いは、端の値が出ない・端だけ出にくい、の2つです。JavaScript で 1〜6 のつもりの式を60万回ずつ実行し、出た回数を数えました。
| 式 | 出た値と回数 | 結果 |
|---|---|---|
Math.floor(r * 6) + 1 |
1:100043 2:100168 3:100063 4:100063 5:100073 6:99590 | 1〜6 がほぼ同じ回数 |
Math.round(r * 5) + 1 |
1:60104 2:119699 3:119808 4:120078 5:120110 6:60201 | 1 と 6 が半分しか出ない |
Math.floor(r * 6) |
0:100174 1:99967 2:100035 3:100072 4:99720 5:100032 | 0〜5 になる(1 を足し忘れ) |
Math.floor(r * (6 - 1)) + 1 |
1:119534 2:119973 3:120252 4:119978 5:120263 | 6 が一度も出ない |
(r は Math.random() です。)Math.round を使うと、1 になるのは r×5 が 0〜0.5 のとき、2 になるのは 0.5〜1.5 のときなので、両端だけ幅が半分になります。PostgreSQL でも round(random() * 5)::int + 1 を6万回実行すると、1 が 6,020 回、6 が 6,122 回で、ほかは約 12,000 回でした。
1〜6 の整数を作る式
覚え方:「個数(最大 − 最小 + 1)を掛けて切り捨て、最小を足す」
Python で 1〜6 を作る
10万回ずつ実行すると、randint(1, 6) は 1〜6、randrange(1, 6) は 1〜5 だけが出た
言語別:端を含むかの一覧
| 書き方 | 下の端 | 上の端 |
|---|---|---|
Python random.randint(1, 6) |
含む | 含む |
Python random.randrange(1, 6) |
含む | 含まない |
JavaScript Math.random() |
0 を含む | 1 を含まない |
Node.js crypto.randomInt(1, 7) |
含む | 含まない |
Java nextInt(6) |
0 を含む | 6 を含まない |
Java nextInt(1, 7) |
含む | 含まない |
PostgreSQL random() |
0.0 を含む | 1.0 を含まない |
bash $RANDOM |
0 を含む | 32767 を含む |
shuf -i 1-6 |
含む | 含む |
小数を整数に直すときも同じ注意が要ります。Python で int(random.uniform(1, 6)) を6万回実行すると 1〜5 しか出ず、round(random.uniform(1, 6)) では 1 が 5,976 回、6 が 6,035 回で、ほかは約 12,000 回でした。
% の余りで出る偏りを数えて確かめる
この節では、乱数を %(割った余り)で範囲に収めたときに出る偏りを、実際に数えた結果と、偏りを避ける方法が分かります。
元の乱数の種類の数が、欲しい範囲の個数で割り切れないと、小さい側の値が少しだけ多く出ます。これを「余りの偏り(モジュロバイアス)」と呼びます。
例として、0〜255 の256通りが同じ割合で出る乱数(1バイト)を % 100 で 0〜99 にします。256 = 100×2 + 56 なので、0〜55 になる元の値は3つずつ(たとえば 5 は 5・105・205)、56〜99 になる元の値は2つずつ(たとえば 60 は 60・160)です。
| 元の乱数 → 余り | 多く出る値 | 少ない値 | 割合の差 |
|---|---|---|---|
| 0〜255 を % 100 | 0〜55(各3通り) | 56〜99(各2通り) | 1.5 倍 |
| 0〜255 を % 6 | 0〜3(各43通り) | 4・5(各42通り) | 約 1.024 倍 |
| 0〜32767 を % 6 | 0・1(各5,462通り) | 2〜5(各5,461通り) | 約 1.0002 倍 |
| 0〜32767 を % 100 | 0〜67(各328通り) | 68〜99(各327通り) | 約 1.003 倍 |
| 0〜32767 を % 10000 | 0〜2767(各4通り) | 2768〜9999(各3通り) | 約 1.33 倍 |
この表は、元の値を全部数え上げて出した数字です。bash の $RANDOM(0〜32767)で $((RANDOM % 6 + 1)) と書いたときの偏りはごく小さいものの、RANDOM % 10000 のように範囲を広げると、小さい側が約 1.33 倍出やすくなります。
実際に100万個で数える
OS の乱数源から100万バイトを取り、% 100 して数えました。
import os
from collections import Counter
N = 1_000_000
c = Counter(x % 100 for x in os.urandom(N))
lo = sum(c[i] for i in range(56)) / 56 # 0〜55 の平均回数
hi = sum(c[i] for i in range(56, 100)) / 44 # 56〜99 の平均回数
print(round(lo, 1), round(hi, 1), round(lo / hi, 3))
11717.1 7814.7 1.499
0〜55 は平均 11,717 回、56〜99 は平均 7,815 回で、計算どおり約 1.5 倍の差が出ました。
偏りを避ける方法:範囲外は引き直す
偏りを避けるには、割り切れる範囲からはみ出た値を捨てて、引き直します。0〜255 を % 100 するなら、200 以上(200〜255 の56通り)が出たら捨てます。残る 0〜199 は、どの余りにもちょうど2通りずつ対応します。
out = [x % 100 for x in os.urandom(N + 400000) if x < 200][:N]
この方法で100万個を数え直すと、0〜55 の平均が 10,006.6 回、56〜99 の平均が 9,991.6 回(比 1.002)になりました。捨てる割合は 56÷256 = 約 21.9% です。記事の先頭のツールも、シードが空のときはこの「範囲外は引き直す」方法で作っています。
自分で書く場合は、言語が用意している「範囲つきの関数」を使うのが近道です。Python の random.randint・secrets.randbelow、Java の nextInt(bound)、Node.js の crypto.randomInt は、範囲を渡すだけで使えます。
重複なしの乱数の作り方(シャッフルして先頭から)
この節では、同じ数が出ない乱数の作り方と、重複ありのときに同じ数が出る確率、並べ替えで起きやすい間違いが分かります。
重複なしの乱数は、「候補を全部並べて、シャッフルして、先頭から必要な個数を取る」と作れます。くじ引きで、引いた札を箱に戻さないのと同じです。
候補を全部並べる
1〜43 なら、1 から 43 までの43個のリストを作る。
シャッフルする
後ろから順に、「自分より前(自分を含む)のどれか1つ」と入れ替えていく。フィッシャー・イェーツのシャッフルと呼ばれる方法。
先頭から必要な個数を取る
先頭の6個を取れば、重複なしの6個になる。見やすくしたいときは最後に小さい順に並べる。
各言語には、この手順をまとめた関数があります。
| 言語 | 重複なしで取る書き方 | 実行結果の例 |
|---|---|---|
| Python | random.sample(range(1, 44), 6) |
13 15 27 29 35 42 |
| Java | Collections.shuffle(list) のあと subList(0, 6) |
33 40 23 27 4 11 |
| PostgreSQL | ORDER BY random() LIMIT 6 |
26 21 41 9 4 12 |
| シェル | shuf -i 1-43 -n 6 |
3 6 17 30 34 43 |
重複ありだと、同じ数はどのくらい出るか
重複ありで作ると、思ったより同じ数が出ます。「n 通りの中から k 個を作ったとき、同じ数が少なくとも1組ある確率」を計算しました。
| 範囲 | 個数 | 同じ数が出る確率 |
|---|---|---|
| 1〜6(サイコロ) | 2個 | 16.67% |
| 1〜6(サイコロ) | 4個 | 72.22% |
| 1〜100 | 10個 | 37.18% |
| 1〜100 | 13個 | 55.72% |
| 0〜9999(4桁) | 100個 | 39.14% |
| 0〜9999(4桁) | 119個 | 50.58% |
1〜100 を10個作ると、37.18% の確率でどれかが重なります。実際に10万回試すと 37.27% で、計算とほぼ同じでした。先ほどツールでシード 2026 の結果に 41 が2回出たのも、この範囲の出来事です。番号を配る・順番を決めるなど、重なると困る用途では「重複なし」を選びます。
並べ替えでよくある間違い
JavaScript で配列をシャッフルするとき、sort(() => Math.random() - 0.5) と書く例を見かけます。[1, 2, 3] を60万回並べ替えて、6通りの並びがそれぞれ何回出たかを数えました。
| 方法 | 123 | 132 | 213 | 231・312・321 |
|---|---|---|---|---|
sort(() => Math.random() - 0.5) |
225,185 | 37,811 | 74,882 | 37,437・37,316・187,369 |
| 全部の位置と入れ替える書き方 | 89,449 | 111,531 | 110,705 | 111,259・88,985・88,071 |
| フィッシャー・イェーツ | 99,921 | 100,067 | 100,369 | 99,820・100,258・99,565 |
どの並びも10万回前後になるはずですが、sort を使う書き方(Node.js 22 で実行)では「123」が約22万回、「132」が約3.8万回と大きく偏りました。2行目は、i 番目を「配列全体のどれか」と入れ替える書き方で、これも偏ります。偏りが出ない書き方は次のとおりです。
function shuffle(a) {
for (let i = a.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1)); // 0〜i のどれか
[a[i], a[j]] = [a[j], a[i]];
}
return a;
}
乱数に偏りがないかの確かめ方(サイコロ6万回とカイ二乗)
この節では、作った乱数が偏っていないかを、数えることとカイ二乗の計算で確かめる方法が分かります。
確かめ方の基本は、「たくさん出して、値ごとの回数を数え、期待した回数とのずれを1つの数にまとめる」ことです。このまとめた数がカイ二乗(χ²)の値です。
Python でサイコロ(1〜6)を6万回振りました。偏りが無ければ、どの目も 10,000 回が期待される回数です。
import random
from collections import Counter
from scipy.stats import chi2
random.seed(20261111)
c = Counter(random.randint(1, 6) for _ in range(60000))
x2 = sum((c[i] - 10000) ** 2 / 10000 for i in range(1, 7))
print(dict(sorted(c.items())))
print(round(x2, 3), round(chi2.sf(x2, 5), 3), round(chi2.ppf(0.95, 5), 3))
{1: 9882, 2: 10037, 3: 10204, 4: 9996, 5: 9969, 6: 9912}
6.563 0.255 11.07
| 目 | 出た回数 | 期待との差 | 差の2乗 ÷ 期待 |
|---|---|---|---|
| 1 | 9,882 | −118 | 1.392 |
| 2 | 10,037 | +37 | 0.137 |
| 3 | 10,204 | +204 | 4.162 |
| 4 | 9,996 | −4 | 0.002 |
| 5 | 9,969 | −31 | 0.096 |
| 6 | 9,912 | −88 | 0.774 |
| 合計 | 60,000 | 0 | 6.563(カイ二乗の値) |
カイ二乗の値の読み方
- 1値ごとに「(出た回数 − 期待の回数)の2乗 ÷ 期待の回数」を計算する3 の目なら (10204 − 10000)² ÷ 10000 = 4.162
- 2全部を足す → カイ二乗の値6つを足して 6.563
- 3自由度(値の種類 − 1)の基準値と比べるサイコロは自由度 5。有意水準 5% の基準値は 11.07、1% は 15.086
- 4基準値より小さければ「偏っているとは言えない」6.563 は 11.07 より小さい。p値は 0.255
結果は「偏っているとは言えない」です。「偏りが無いと証明された」わけではない点に注意が要ります。p値の読み方は、関連記事「p値とは|意味・有意水準・よくある誤解をPythonで実演」で扱っています。
偏った式・ほかの乱数で同じ計算をする
| 作り方(1〜6 を6万回) | カイ二乗 | p値 | 読み取り |
|---|---|---|---|
Python random.randint(1, 6) |
6.563 | 0.255 | 偏っているとは言えない |
| 記事のツール(シード空・1万個×6回) | 5.089 | 0.405 | 偏っているとは言えない |
SQLite abs(random()) % 6 + 1 |
3.001 | 0.700 | 偏っているとは言えない |
PostgreSQL floor(random() * 6) + 1 |
2.698 | 0.746 | 偏っているとは言えない |
round(random() * 5) + 1(端が半分になる式) |
4950.3 | ほぼ 0 | はっきり偏っている |
0〜255 を % 6 して +1 |
9.567 | 0.088 | 6万回では見つからなかった |
記事のツールで出た回数は、1 が 10,003、2 が 10,138、3 が 10,099、4 が 9,893、5 が 9,963、6 が 9,904 でした。
最後の行が大事な点です。0〜255 を % 6 する式には約 1.024 倍の偏りがあると前の節で数えましたが、6万回のカイ二乗では基準値(11.07)を超えませんでした。小さな偏りは、回数が少ないと数えても見つかりません。式に偏りが無いかは、数えるだけでなく、前の節のように「元の値が割り切れるか」を式から確かめるのが確実です。
回数が少ないと、ばらついて見える
偏りの無い乱数でも、回数が少ないとずれが大きく見えます。サイコロを振る回数を変えて、期待の回数からいちばん外れた目のずれを調べました。
| 振った回数 | いちばん少ない目 | いちばん多い目 | 期待からの最大のずれ |
|---|---|---|---|
| 60 | 6 回 | 14 回 | 40.0% |
| 600 | 88 回 | 116 回 | 16.0% |
| 6,000 | 967 回 | 1,025 回 | 3.3% |
| 60,000 | 9,870 回 | 10,084 回 | 1.3% |
| 600,000 | 99,568 回 | 100,417 回 | 0.43% |
60回では、ある目が6回、別の目が14回と2倍以上の差が出ました。「同じ数ばかり出る」と感じても、回数が少ないうちは乱数の性質の範囲です。
用途別の判断表(抽選・テストデータ・シミュレーション)
この節では、乱数を使う目的ごとに、どの種類の乱数を選び、シードをどうするかが分かります。
選ぶ基準は「あとで同じ結果を出したいか」と「予測されると困るか」の2つです。
| 用途 | 向く乱数 | シード | 書き方の例 |
|---|---|---|---|
| 順番決め・担当決め・抽選 | 暗号用の乱数(予測しにくい) | 指定しない | 記事のツール(シード空)、secrets.choice、shuf |
| テストデータ | 疑似乱数 | 固定する | random.seed(2026)、new Random(42) |
| シミュレーション | 疑似乱数(速い) | 固定して記録する | random.seed(42)、setseed(0.42) |
| ゲームの演出・画面の飾り | 疑似乱数 | どちらでもよい | Math.random() |
| 表からランダムに数行を選ぶ | データベースの乱数 | 再現したいなら固定 | ORDER BY random() LIMIT 3 |
| 鍵・トークンなど秘密の値 | 暗号用の乱数と専用の機能 | 指定しない | secrets、SecureRandom、Web Crypto |
鍵やトークンには、暗号用の乱数を使います。MDN は、暗号鍵の生成には getRandomValues() ではなく generateKey() を使うよう案内しており、言語やブラウザーが用意する専用の機能を選ぶのが基本です。
抽選や順番決めで使うときの確認点
- 1候補の一覧を先に決めて見せる並べ替える前のリスト(名前や番号)を、関係する人が確かめられるようにする
- 2重複なしにするかを決める同じ人・同じ番号が2回選ばれてよいかどうか。順番決めは重複なし
- 3やり直しの決まりを先に決める結果を見てから引き直すと、乱数で決めた意味が薄れる
- 4条件と結果を残す範囲・個数・重複の有無・結果をメモに残す。確かめ直せる形にしたいときは、シードを先に決めて記録する
シミュレーションでの使い方(円周率の例)
乱数をたくさん使って答えを近似する方法を、モンテカルロ法と呼びます。0〜1 の乱数を2つ使って点を打ち、原点からの距離が1未満の点の割合を4倍すると、円周率に近づきます。シード 42 で回数を変えて実行しました。
import random
for n in (1000, 10000, 100000, 1000000):
random.seed(42)
hit = sum(random.random() ** 2 + random.random() ** 2 < 1 for _ in range(n))
print(n, 4 * hit / n)
1000 3.128
10000 3.126
100000 3.13728
1000000 3.140592
100万回で 3.140592(円周率との差は約 0.001)でした。回数を増やすと近づきますが、近づき方はゆっくりです。シードを固定しているので、この数字は何度実行しても同じになります。
乱数生成でよくあるエラー・つまずき
この節では、乱数のプログラムで出やすいエラーの原文と、原因・直し方が分かります。
エラーの多くは「範囲が逆」「候補より多く取ろうとした」「上限が 0 以下」のどれかです。実際に出したエラーを表にまとめます。
| エラー・症状(原文) | 原因 | 直し方 |
|---|---|---|
Python:ValueError: Sample larger than population or is negative |
random.sample(range(1, 11), 11) のように、候補より多く取ろうとした |
個数を候補の数以下にする。重複ありでよければ random.choices |
Python:ValueError: empty range in randrange(6, 2) |
random.randint(6, 1) のように最小と最大が逆 |
小さい方を先に書く |
Python:IndexError: Cannot choose from an empty sequence |
random.choice([]) と、空のリストから選ぼうとした |
選ぶ前に、リストが空でないか確かめる |
Java:IllegalArgumentException: bound must be positive |
nextInt(0) と、上限に 0 以下を渡した |
上限は 1 以上にする |
Java:IllegalArgumentException: bound must be greater than origin |
nextInt(7, 1) と、範囲が逆 |
小さい方を先に書く |
Node.js:RangeError [ERR_OUT_OF_RANGE]: The value of "max" is out of range. |
crypto.randomInt(7, 1) と、範囲が逆 |
min より大きい max を渡す |
JavaScript:QuotaExceededError: The requested length exceeds 65,536 bytes |
getRandomValues に 65,536 バイトを超える配列を渡した | 配列を分けて、何回かに分けて呼ぶ |
PostgreSQL:function random(integer, integer) does not exist |
PostgreSQL 16 で random(1, 6) と書いた |
floor(random() * 6)::int + 1 と書く |
| 毎回同じ乱数になる | シードを固定したまま、またはループの中で同じシードの生成器を作り直している | 生成器は1回だけ作って使い回す。固定が不要ならシードの指定を外す |
| 上限の値が一度も出ない | randrange(1, 6)・nextInt(6) など、上の端を含まない関数 |
上限に 1 を足す。端の一覧表で確かめる |
Java で Math.abs(r.nextInt()) % 6 と書く方法にも落とし穴があります。Math.abs(Integer.MIN_VALUE) % 6 を実行すると -2 になりました。絶対値を取っても負のままの値が1つだけあるためです。範囲つきの nextInt(6) を使えば起きません。
乱数生成のよくある質問
この節では、乱数生成について検索されることの多い疑問に、短く答えます。
Q. 乱数生成ツールで作った数は、本当にランダムですか?
A. シードが空のときは、ブラウザの暗号用の乱数(crypto.getRandomValues)で作り、余りの偏りを避けるため範囲外は引き直しています。サイコロの設定で6万個を作って数えたところ、カイ二乗の値は 5.089(p値 0.405)で、偏っているとは言えない結果でした。
Q. 重複なしで乱数を作るにはどうしますか?
A. ツールでは「重複なし」にチェックを入れます。プログラムでは、候補をシャッフルして先頭から取ります。Python は random.sample(range(1, 101), 10)、シェルは shuf -i 1-100 -n 10 です。
Q. 1〜100 の乱数を10個作ると、同じ数が出る確率はどのくらいですか?
A. 重複ありで作った場合、少なくとも1組が重なる確率は 37.18% です。13個なら 55.72% で、半分を超えます。
Q. 同じ乱数をもう一度出すことはできますか?
A. シードを固定するとできます。ツールでは「シード(任意)」に同じ文字を入れ、同じ設定で押します。Python は random.seed(42)、Java は new Random(42)、PostgreSQL は setseed(0.42) です。
Q. Math.random() にシードは指定できますか?
A. できません。MDN は、初期シードは実装側が選び、利用者は選択もリセットもできないと説明しています。再現したいときは、この記事の mulberry32 のようなシードつきの生成器を使います。
Q. 疑似乱数と真の乱数は、どちらを使えばよいですか?
A. テストデータやシミュレーションは、速くて再現できる疑似乱数が向きます。予測されて困る値には、OS の乱数源をもとにした暗号用の乱数を使います。真の乱数を直接使う場面は、ふだんのプログラムではほとんどありません。
Q. 小数の乱数を作るにはどうしますか?
A. ツールでは「小数第1位まで」〜「小数第3位まで」を選びます。プログラムでは、Python の random.uniform(a, b) や、JavaScript の Math.random() * (max - min) + min を使います。
Q. このツールでパスワードやトークンを作ってもよいですか?
A. このツールは、パスワードや鍵を作る用途のものではありません。そうした値には、暗号用の乱数を使う専用の機能(パスワード管理ソフトの生成機能や、言語の secrets・SecureRandom など)を使います。
Q. 同じ数ばかり出る気がします。偏っていますか?
A. 回数が少ないうちは、偏りの無い乱数でも大きくばらつきます。サイコロ60回では、ある目が6回、別の目が14回でした。偏りを確かめるには、数千〜数万回出して数えます。
Q. 入力した内容は、どこかに送信されますか?
A. 送信されません。Chromium で操作したときに発生した通信は、ページ本体と、表示用の CSS・JavaScript の読み込みだけでした。乱数はこの端末の中で作っています。
Q. 一度に何個まで作れますか?
A. ツールでは1回に 10,000 個までです。それより多いときは、この記事のコードのようにプログラムで作ります。
まとめ
この節では、乱数生成について押さえておきたい点を5つにまとめます。
- 乱数生成は、最小・最大・個数を決めれば、記事の先頭のツールですぐできます。重複なし・小数・並べ替え・リストのシャッフルにも対応しています。
- プログラムの乱数のほとんどは疑似乱数で、シードから計算で作ります。同じシードなら同じ並びになり、テストデータや不具合の再現に使えます。
- 範囲の端を含むかは、関数ごとに違います。Python の randint は両端を含み、randrange・Java の nextInt・Math.random は上の端を含みません。
- % の余りと Math.round は偏りのもとになります。0〜255 を % 100 すると 0〜55 が 1.5 倍出やすく、round を使うと両端が半分になりました。範囲つきの関数を使うか、範囲外を引き直します。
- 偏りは、たくさん出して数え、カイ二乗で確かめます。サイコロ6万回の値は 6.563 で、基準値 11.07 より小さく、偏っているとは言えない結果でした。小さな偏りは、式から確かめるのが確実です。
参考・出典
この節では、この記事で確かめた公式ドキュメントを一覧にします(確認日 2026年11月11日)。
- Python「random --- 擬似乱数を生成する」:https://docs.python.org/ja/3/library/random.html
- Python「secrets --- 機密を扱うために安全な乱数を生成する」:https://docs.python.org/ja/3/library/secrets.html
- MDN「Math.random()」:https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Math/random
- MDN「Crypto: getRandomValues() メソッド」:https://developer.mozilla.org/ja/docs/Web/API/Crypto/getRandomValues
- Oracle「Java SE 21 API:java.util.Random」:https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/Random.html
- SQLite「Built-In Scalar SQL Functions」(random・abs):https://www.sqlite.org/lang_corefunc.html
- PostgreSQL 16「Mathematical Functions and Operators」(Random Functions):https://www.postgresql.org/docs/16/functions-math.html
- GNU Bash Reference Manual「Bash Variables」(RANDOM):https://www.gnu.org/software/bash/manual/html_node/Bash-Variables.html
- GNU Coreutils「shuf: Shuffling text」:https://www.gnu.org/software/coreutils/manual/html_node/shuf-invocation.html
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「乱数生成ツール|範囲・個数・重複なしで作る方法とプログラムでの作り方」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。