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})