Pythonには、さまざまな乱数の分布を生成する方法がいくつかあります。モジュールのドキュメントをrandom
参照してください。残念ながら、特に必要なパラメータを考慮すると、適切な数学の背景がなければ、それらはひどく理解できません。
これらの方法のいずれかが、ベンフォードの法則に従う分布を持つ乱数を生成できるかどうか、およびどのパラメーター値が適切であるかを知りたいです。つまり、整数の母集団の場合、これらの整数は、約30%の確率で「1」で始まり、約18%の確率で「2」で始まる必要があります。
John Dvorakの答えを使用して、次のコードをまとめましたが、完全に機能しているように見えます。
def benfords_range_gen(stop, n):
""" A generator that returns n random integers
between 1 and stop-1 and whose distribution
meets Benford's Law i.e. is logarithmic.
"""
multiplier = math.log(stop)
for i in range(n):
yield int(math.exp(multiplier * random.random()))
>>> from collections import Counter
>>> Counter(str(i)[0] for i in benfords_range_gen(10000, 1000000))
Counter({'1': 300696, '2': 176142, '3': 124577, '4': 96756, '5': 79260, '6': 67413, '7': 58052, '8': 51308, '9': 45796})
これが異なるバージョンのPython間で一貫して機能するかどうかについても疑問が生じています。乱数の性質上、これは簡単な質問ではありません。実行ごとに、場合によってはrandom
ライブラリの異なるバージョン間で、ある程度の変動が予想されます。これを回避する唯一の方法は、実行ごとに一貫して乱数ジェネレーターをシードすることです。これをテストに追加したところ、Python 2.7.1、3.8.6、および3.9.1でもまったく同じ結果が得られました。
>>> random.seed(7919)
>>> Counter(str(i)[0] for i in benfords_range_gen(10000, 1000000))
Counter({'1': 301032, '2': 176404, '3': 125350, '4': 96503, '5': 78450, '6': 67198, '7': 58000, '8': 51342, '9': 45721})