線形合同法 (linear congruential generator: LCG) は、最も古く、また最もよく知られた擬似乱数生成アルゴリズムの一種。
概要¶
生成周期について¶
周期の最大は
以下の条件をすべて満たすと周期が最大になる:
と が互いに素(最大公約数が1)
が の全ての素因数で割り切れる
が 4 の倍数ならば も 4 の倍数
実装¶
pythonでいうと
x = (A * x + C) % Mで済む。クラスにするなら以下のようになる。
class LCG:
def __init__(self, A, C, M, x_0):
self.A = A
self.C = C
self.M = M
self.x = x_0
def gen(self):
self.x = (self.A * self.x + self.C) % self.M
return self.xrandom = LCG(A=123, C=456, M=789, x_0=1)
for trial in range(5):
x = random.gen()
print(f"{trial}: {x=}")0: x=579
1: x=663
2: x=738
3: x=495
4: x=588
パラメータを変えて実験¶
# 周期が最大になる例
random = LCG(A=13, C=5, M=12, x_0=0)
# 最大周期を確認するためM+1回繰り返す
for trial in range(random.M + 1):
x = random.gen()
print(f"{trial+1}: {x=}")1: x=5
2: x=10
3: x=3
4: x=8
5: x=1
6: x=6
7: x=11
8: x=4
9: x=9
10: x=2
11: x=7
12: x=0
13: x=5
# 周期が最大にならない例
random = LCG(A=999, C=999, M=999, x_0=1)
for trial in range(5):
x = random.gen()
print(f"{trial+1}: {x=}")1: x=0
2: x=0
3: x=0
4: x=0
5: x=0
random = LCG(A=13, C=5, M=12, x_0=0)
for trial in range(6):
x = random.gen()
print(f"{trial+1}: {x=}")1: x=5
2: x=10
3: x=3
4: x=8
5: x=1
6: x=6
参考¶
- Park, S. K., & Miller, K. W. (1988). Random number generators: good ones are hard to find. Communications of the ACM, 31(10), 1192–1201. 10.1145/63039.63042