Python には何通りかの乱数が用意されています。ここではシミュレーション用の乱数を説明します。パスワード生成のためには安全な乱数をご覧ください。
random は標準ライブラリのモジュールですのでインストールする必要はありません。Mersenne Twister が使われています。
import random random.random() # 引数をとらない。区間 [0,1) の1個の乱数を返す random.randrange(1, 7) # 1から6までの整数の乱数 random.randint(1, 6) # 1から6までの整数の乱数
本格的なシミュレーションで大量の乱数を必要とする場合には次の NumPy による方法を使います。
numpy.random を使います。
Mersenne Twister が使われています。
import numpy as np np.random.random(10) # 0以上1未満の一様乱数10個 np.random.randint(1, 7, size=10) # 1以上7未満の整数の乱数10個
2013年にリリースされた NumPy 1.17.0 からは Generator を使った新しいインターフェースが推奨されています(NumPy のバージョンは np.__version__
でわかります)。デフォルトのアルゴリズムは PCG64 です。これは次のようにして使います:
import numpy as np rng = np.random.default_rng(348309421) # seedの設定(空も可) rng.random() # 0以上1未満の一様乱数 rng.random(10) # 0以上1未満の一様乱数10個の配列 rng.normal(5, 3) # 平均5,標準偏差3の正規分布の乱数 rng.normal(5, 3, 10) # 平均5,標準偏差3の正規分布の乱数10個の配列 rng.standard_normal() # 標準正規分布(平均0,標準偏差1)の乱数 rng.standard_normal(10) # 標準正規分布の乱数10個の配列 rng.integers(1, 7) # 1以上7未満の整数の乱数 rng.integers(1, 7, 10) # 1以上7未満の整数の乱数10個の配列 rng.exponential(3) # 平均3の指数分布の乱数 rng.exponential(3, 10) # 平均3の指数分布の乱数10個の配列
上の例のように「タネ(seed)」を与えるのがシミュレーションでの推奨です。同じタネからは同じ乱数列が生成されますので,あとで結果を再現できます。ゲームなどでは rng = np.random.default_rng()
のように空にすると,再現性のない(毎回異なる)乱数列が得られます。
乱数のタネとしては、その日の日付でも何でもいいのですが、たまたま自分の都合の良い結果が出るようなタネを採用したのではないかと疑われないように、自分のORCIDをタネに使うのも一つの手です。ORCID(Open Researcher and Contributor ID)は研究者用のIDで、https://orcid.org に登録すれば無料で発行してもらえます。私のORCIDは 0000-0003-4830-9421 ですので、頭の0と区切りのマイナスを取り除いた 348309421 を上の例で使っています。
例えばモンテカルロ法で円周率を求めるには次のようにします:
import matplotlib.pyplot as plt N = 10000 x = rng.random(N) y = rng.random(N) c = x*x + y*y < 1 plt.scatter(x, y, c=c) plt.axis('scaled') print('pi =', 4 * np.sum(c) / N)
ランダムウォークの例です:
N = 1000 x = np.cumsum(rng.random(N) - 0.5) y = np.cumsum(rng.random(N) - 0.5) plt.plot(x, y) plt.axis('equal')
硬貨投げのシミュレーションは rng.integers(0, 2, size=100)
のようにできます。表の枚数は np.sum(rng.integers(0, 2, size=100))
です。これを何回もやってヒストグラムを描いてみましょう。
a = [np.sum(rng.integers(0, 2, size=100)) for _ in range(10000)] plt.hist(a, bins=range(min(a), max(a)+2), align="left", edgecolor="black")
plt.hist()
のオプションがわずらわしいなら seaborn を使いましょう:
import seaborn as sns sns.histplot(a, discrete=True)