前のトピックへ

9.5. fractions — 有理数

次のトピックへ

9.7. itertools — 効率的なループ実行のためのイテレータ生成関数

このページ

9.6. random — 擬似乱数を生成する

このモジュールでは様々な分布をもつ擬似乱数生成器を実装しています。整数用では、ある値域内の数の選択を一様にします。シーケンス用には、シーケンスからのランダムな要素の一様な選択、リストの要素の順列をランダムに置き換える関数、順列を入れ替えずにランダムに取り出す関数があります。

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

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

このモジュールで提供されている関数は、実際には 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 で変更: MersenneTwister が Wichmann-Hill の代わりにデフォルト生成器になりました。

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

保守関数:

random.seed([x])

基本乱数生成器を初期化します。オプション引数 x はハッシュ可能(hashable)な任意のオブジェクトをとり得ます。 x が省略されるか None の場合、現在のシステム時間が使われます; 現在のシステム時間はモジュールが最初にインポートされた時に乱数生成器を初期化するためにも使われます。

乱数の発生源をオペレーティングシステムが提供している場合、システム時刻の代わりにその発生源が使われます(詳細については os.urandom() 関数を参照)。

バージョン 2.4 で変更: 通常、オペレーティングシステムのリソースは使われません.

xNone でも、整数でも長整数でもない場合、 hash(x) が代わりに使われます。 x が整数または長整数の場合、 x が直接使われます。

random.getstate()

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

バージョン 2.1 で追加.

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

random.setstate(state)

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

バージョン 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([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 であるようなランダムな浮動小数点数 N を返し、 b < a であれば b <= N <= a になります。

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

random.triangular(low, high, mode)

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

バージョン 2.6 で追加.

random.betavariate(alpha, beta)

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

random.expovariate(lambd)

指数分布です。 lambd は平均にしたい値で 1.0 を割ったものです。 (このパラメタは “lambda” と呼ぶべきなのですが、Python の予約語なので使えません。) 返される値の範囲は 0 から正の無限大です。

random.gammavariate(alpha, beta)

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

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.