# 9.6. `random` --- 擬似乱数を生成する

ソースコード: Lib/random.py

このモジュールでは様々な分布をもつ擬似乱数生成器を実装しています。

整数用では、ある値域内の数の選択を一様にします。シーケンス用には、シーケンスからのランダムな要素の一様な選択、リストの要素の順列をランダムに置き換える関数、順列を入れ替えずにランダムに取り出す関数があります。

実数用としては、一様分布、正規分布 (ガウス分布)、対数正規分布、負の指数分布、ガンマおよびベータ分布を計算する関数があります。角度分布の生成用には、フォンミーゼス分布が利用できます。

ほとんど全てのモジュール関数は、基礎となる関数 `random()` に依存します。この関数はランダムな浮動小数点数を半開区間 [0.0, 1.0) 内に一様に生成します。Python は中心となる乱数生成器としてメルセンヌツイスタを使います。これは 53 ビット精度の浮動小数点を生成し、周期は 2**19937-1 です、本体は C で実装されていて、高速でスレッドセーフです。メルセンヌツイスタは、現存する中で、最も広範囲にテストされた乱数生成器のひとつです。しかし、完全に決定論的であるため、この乱数生成器は全ての目的に合致しているわけではなく、暗号化の目的には全く向いていません。

このモジュールで提供されている関数は、実際には `random.Random` クラスの隠蔽されたインスタンスのメソッドにバインドされています。内部状態を共有しない生成器を取得するため、自分で `Random` のインスタンスを生成することができます。異なる `Random` のインスタンスを各スレッド毎に生成し、 `jumpahead()` メソッドを使うことで各々のスレッドにおいて生成された乱数列ができるだけ重複しないようにすれば、マルチスレッドプログラムを作成する上で特に便利になります。

自分で考案した基本乱数生成器を使いたい場合、クラス `Random` をサブクラス化することもできます。 この場合、メソッド `random()` 、 `seed()` 、 `getstate()` 、 `setstate()` 、 `jumpahead()` をオーバライドしてください。 オプションとして、新しいジェネレータは `getrandbits()` メソッドを提供することができます。 これにより `randrange()` メソッドが任意に大きな範囲から選択を行えるようになります。

バージョン 2.4 で追加: `getrandbits()` メソッド.

サブクラス化の例として、 `random` モジュールは `WichmannHill` クラスを提供します。このクラスは Python だけで書かれた代替生成器を実装しています。このクラスは、乱数生成器に Wichmann-Hill 法を使っていた古いバージョンの Python から得られた結果を再現するための、後方互換の手段になります。ただし、この Wichmann-Hill 生成器はもはや推奨することができないということに注意してください。現在の水準では生成される周期が短すぎ、また厳密な乱数性試験に合格しないことが知られています。こうした欠点を修正した最近の改良についてはページの最後に挙げた参考文献を参照してください。

バージョン 2.3 で変更: メルセンヌツイスタが Wichmann-Hill の代わりにデフォルト生成器になりました。

`random` モジュールは `SystemRandom` クラスも提供していて、このクラスは OS が提供している乱数発生源を利用して乱数を生成するシステム関数 `os.urandom()` を使うものです。

警告

このモジュールの擬似乱数生成器はセキュリティ上の手段に使うべきではありません。暗号学的にセキュアな疑似乱数生成器が必要なら、 `os.urandom()` や `SystemRandom` を使ってください。

保守(bookkeeping)関数:

`random.``seed`(a=None)

  乱数生成器の内部状態を初期化します。

  引数が `None` または無い場合は、現在時刻もしくは利用可能ならオペレーティングシステム固有の乱数発生源をシードとします (利用可能かどうかについての詳細は `os.urandom()` 関数を参照してください)。

  a が `None` や `int` や `long` でない場合は `hash(a)` を代わりに使います。 `PYTHONHASHSEED` が有効なときは、ある型のハッシュ値は非決定的であることに注意してください。

  バージョン 2.4 で変更: 以前は、オペレーティングシステムのリソースは使われませんでした。

`random.``getstate`()

  乱数生成器の現在の内部状態を記憶したオブジェクトを返します。このオブジェクトを `setstate()` に渡して内部状態を復帰することができます。

  バージョン 2.1 で追加.

  バージョン 2.6 で変更: Python 2.6 が作り出す状態オブジェクトは以前のバージョンには読み込めません。

`random.``setstate`(state)

  state は予め `getstate()` を呼び出して得ておかなくてはなりません。 `setstate()` は `getstate()` が呼び出された時の乱数生成器の内部状態を復帰します。

  バージョン 2.1 で追加.

`random.``jumpahead`(n)

  内部状態を、現在の状態から、非常に離れているであろう状態に変更します。 n は非負の整数です。これはマルチスレッドのプログラムが複数の `Random` クラスのインスタンスと結合されている場合に非常に便利です: `setstate()` や `seed()` は全てのインスタンスを同じ内部状態にするのに使うことができ、その後 `jumpahead()` を使って各インスタンスの内部状態を引き離すことができます。

  バージョン 2.1 で追加.

  バージョン 2.3 で変更: n ステップ先の特定の状態になるのではなく、 `jumpahead(n)` は何ステップも離れているであろう別の状態にする。

`random.``getrandbits`(k)

  k ビット分の乱数ビットを納めた Python の `long` 整数を返します。このメソッドは MersenneTwister 生成器で提供されており、その他の乱数生成器でもオプションのAPIとして提供されているかもしれません。このメソッドが使えるとき、 `randrange()` メソッドは大きな範囲を扱えるようになります。

  バージョン 2.4 で追加.

整数用の関数:

`random.``randrange`(stop)
`random.``randrange`(start, stop[, step])

  `range(start, stop, step)` の要素からランダムに選ばれた要素を返します。この関数は `choice(range(start, stop, step))` と等価ですが、実際には range オブジェクトを生成しません。

  バージョン 1.5.2 で追加.

`random.``randint`(a, b)

  `a <= N <= b` であるようなランダムな整数 N を返します。

シーケンス用の関数:

`random.``choice`(seq)

  空でないシーケンス seq からランダムに要素を返します。 seq が空のときは、 `IndexError` が送出されます。

`random.``shuffle`(x[, random])

  シーケンス x をインプレースにシャッフルします。オプションの引数 random は、引数を持たず、 [0.0, 1.0) のランダムな浮動小数点数を返すような関数です。デフォルトでは、これは関数 `random()` です。

  やや小さい `len(x)` であっても、 x の順列の総数はほとんどの乱数生成器の周期よりも大きくなるので注意してください; このことは長いシーケンスに対してはほとんどの順列は生成されないことを意味します。

`random.``sample`(population, k)

  母集団のシーケンスから選ばれた長さ k の一意な要素からなるリストを返します。値の置換を行わないランダムサンプリングに用いられます。

  バージョン 2.3 で追加.

  母集団自体を変更せずに、母集団内の要素を含む新たなリストを返します。返されたリストは選択された順に並んでいるので、このリストの部分スライスもランダムなサンプルになります。これにより、くじの当選者 (サンプル) を1等賞と2等賞（の部分スライス）に分けることも可能です。

  母集団の要素はハッシュ可能 (hashable) でなくても、ユニークでなくても、かまいません。母集団が繰り返しを含む場合、出現するそれぞれがサンプルに選択されえます。

  整数の並びからサンプルを選ぶには、引数に `xrange()` オブジェクトを使いましょう。特に、巨大な母集団からサンプルを取るとき、速度と空間効率が上がります。 `sample(xrange(10000000), 60)`

以下の関数は特定の実数値分布を生成します。関数の引数の名前は、一般的な数学の慣例で使われている分布の公式の対応する変数から取られています; これらの公式のほとんどはどんな統計学のテキストにも載っています。

`random.``random`()

  値域 [0.0, 1.0) の次のランダムな浮動小数点数を返します。

`random.``uniform`(a, b)

  `a <= b` であれば `a <= N <= b` 、`b < a` であれば `b <= N <= a` であるようなランダムな浮動小数点数 N を返します。

  端点の値 `b` が範囲に含まれるかどうかは、等式 `a + (b-a) * random()` における浮動小数点の丸めに依存します。

`random.``triangular`(low, high, mode)

  `low <= N <= high` でありこれら境界値の間に指定された最頻値 mode を持つようなランダムな浮動小数点数 N を返します。境界 low と high のデフォルトは 0 と 1 です。最頻値 mode 引数のデフォルトは両境界値の中点になり、対称な分布を与えます。

  バージョン 2.6 で追加.

`random.``betavariate`(alpha, beta)

  ベータ分布です。引数の満たすべき条件は `alpha > 0` および `beta > 0` です。範囲 0 から 1 の値を返します。

`random.``expovariate`(lambd)

  指数分布です。lambd は平均にしたい値の逆数です。(この引数は "lambda" と呼ぶべきなのですが、Python の予約語なので使えません。) 返される値の範囲は lambd が正なら 0 から正の無限大、lambd が負なら負の無限大から 0 です。

`random.``gammavariate`(alpha, beta)

  ガンマ分布です。 (ガンマ関数 ではありません ！) 引数の満たすべき条件は `alpha > 0` および `beta > 0` です。

  確率分布関数は:

                x ** (alpha - 1) * math.exp(-x / beta)
      pdf(x) =  --------------------------------------
                  math.gamma(alpha) * beta ** alpha

`random.``gauss`(mu, sigma)

  ガウス分布です。 mu は平均であり、 sigma は標準偏差です。この関数は後で定義する関数 `normalvariate()` より少しだけ高速です。

`random.``lognormvariate`(mu, sigma)

  対数正規分布です。この分布を自然対数を用いた分布にした場合、平均 mu で標準偏差 sigma の正規分布になります。 mu は任意の値を取ることができ、sigma はゼロより大きくなければなりません。

`random.``normalvariate`(mu, sigma)

  正規分布です。 mu は平均で、 sigma は標準偏差です。

`random.``vonmisesvariate`(mu, kappa)

  mu は平均の角度で、0 から 2*pi までのラジアンで表されます。 kappa は濃度パラメタで、ゼロ以上でなければなりません。kappa がゼロに等しい場合、この分布は範囲 0 から 2*pi の一様でランダムな角度の分布に退化します。

`random.``paretovariate`(alpha)

  パレート分布です。 alpha は形状パラメタです。

`random.``weibullvariate`(alpha, beta)

  ワイブル分布です。 alpha は尺度パラメタで、 beta は形状パラメタです。

代替の乱数生成器:

class `random.``WichmannHill`([seed])

  乱数生成器として Wichmann-Hill アルゴリズムを実装するクラスです。 `Random` クラスと同じメソッド全てと、下で説明する `whseed()` メソッドを持ちます。このクラスは、Python だけで実装されているので、スレッドセーフではなく、呼び出しと呼び出しの間にロックが必要です。また、周期が 6,953,607,871,644 と短く、独立した2つの乱数列が重複しないように注意が必要です。

`random.``whseed`([x])

  これは obsolete で、バージョン 2.1 以前の Python と、ビット・レベルの互換性のために提供されてます。詳細は `seed()` を参照してください。 `whseed()` は、引数に与えた整数が異なっても、内部状態が異なることを保障しません。取り得る内部状態の個数が 2**24 以下になる場合もあります。

class `random.``SystemRandom`([seed])

  オペレーティングシステムの提供する発生源によって乱数を生成する `os.urandom()` 関数を使うクラスです。すべてのシステムで使えるメソッドではありません。ソフトウェアの状態に依存してはいけませんし、一連の操作は再現不能です。それに応じて、 `seed()` と `jumpahead()` メソッドは何の影響も及ぼさず、無視されます。 `getstate()` と `setstate()` メソッドが呼び出されると、例外 `NotImplementedError` が送出されます。

  バージョン 2.4 で追加.

基本使用例:

    >>> random.random()        # Random float x, 0.0 <= x < 1.0
    0.37444887175646646
    >>> random.uniform(1, 10)  # Random float x, 1.0 <= x < 10.0
    1.1800146073117523
    >>> random.randint(1, 10)  # Integer from 1 to 10, endpoints included
    7
    >>> random.randrange(0, 101, 2)  # Even integer from 0 to 100
    26
    >>> random.choice('abcdefghij')  # Choose a random element
    'c'

    >>> items = [1, 2, 3, 4, 5, 6, 7]
    >>> random.shuffle(items)
    >>> items
    [7, 3, 2, 5, 6, 4, 1]

    >>> random.sample([1, 2, 3, 4, 5],  3)  # Choose 3 elements
    [4, 1, 5]

参考

M. Matsumoto and T. Nishimura, "Mersenne Twister: A 623-dimensionally equidistributed uniform pseudorandom number generator", ACM Transactions on Modeling and Computer Simulation Vol. 8, No. 1, January pp.3--30 1998.

Wichmann, B. A. & Hill, I. D., "Algorithm AS 183: An efficient and portable pseudo-random number generator", Applied Statistics 31 (1982) 188-190.

Complementary-Multiply-with-Carry recipe 長い周期と比較的シンプルな更新操作を備えた互換性のある別の乱数生成器。