是否有符合本福特定律的随机数分布?

时间:2013-01-28 06:17:11

标签: python random benfords-law

Python有多种方法可以生成随机数的不同分布,请参阅documentation for the random module。不幸的是,没有适当的数学背景,它们并不是非常容易理解,特别是考虑到所需的参数。

我想知道这些方法中的任何一种是否能够生成具有服从Benford's Law的分布的随机数,以及哪些参数值是合适的。即对于整数群体,那些整数应该在大约30%的时间以'1'开头,'2'在大约18%的时间开始,等等。

<小时/> 使用Jan 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})

2 个答案:

答案 0 :(得分:20)

本福德定律描述了一组数字的第一个数字的分布,如果数字是从对数尺度上的宽范围中选择的。如果你准备一个十年的对数均匀分布,它也会尊重法律。 10^[0,1)将产生该分发。

这将产生所需的分布:math.floor(10**random.random())

答案 1 :(得分:0)

只是在玩耍。

对于像我这样的人来说效率低得多,但也许更多可见的实现,并不是那么数学倾向......

创建任何所需分发的简单方法是使用所需的项目百分比填充列表,然后使用random.choice(<list>),因为这会返回列表中统一选择的项目。

import random
probs = [30.1, 17.6, 12.5, 9.7, 7.9, 6.7, 5.8, 5.1, 4.6]
nums = [1, 2, 3, 4, 5, 6, 7, 8, 9]
population = sum([[n] * int(p * 10) for n, p in zip(nums, probs)], [])

max_value = 100
min_value = 1
result_pop = []
target_pop_size = 1000
while len(result_pop) < target_pop_size:
    s = str(random.choice(population))
    while True:
        r = random.randint(min_value, max_value)
        if str(r).startswith(s):
            break
    result_pop.append(r)