【发布时间】:2013-01-28 06:17:11
【问题描述】:
Python 有多种方法可以生成不同的随机数分布,请参阅documentation for the random module。不幸的是,如果没有适当的数学背景,尤其是考虑到所需的参数,它们就很难理解。
我想知道这些方法中是否有任何一种能够产生分布服从Benford's Law 的随机数,以及哪些参数值是合适的。即对于整数的总体,这些整数应该在大约 30% 的时间以“1”开头,大约 18% 的时间以“2”开头,等等。
使用John Dvorak's answer,我将以下代码放在一起,它似乎可以完美运行。
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})
【问题讨论】:
-
这不等于在 log(min) 和 log(max) 之间统一选择一个随机数并输出 10 提升到该数字吗?
-
鉴于本福德定律,试试
floor(10^random()) -
@JanDvorak:是的。对于 1,000,000 次试验,我得到:
{1: 0.301143, 2: 0.175899, 3: 0.125316, 4: 0.097045, 5: 0.079359, 6: 0.066662, 7: 0.057795, 8: 0.050963, 9: 0.045818}。在 Python 中,它是int(10**random.random()) -
@Blender 所以,看起来是正确的
-
@JanDvorak,如果您是认真的,请提出它作为答案。我喜欢它不依赖于任何花哨的分布模型,只是对通常的等概率的简单转换。
标签: python random benfords-law