生成总和为预定义值的随机数

2024-01-05

所以事情是这样的:我想(例如)生成 4 个伪随机数,加在一起等于 40。这怎么可能是 python 中的圆顶?我可以生成一个随机数 1-40,然后生成 1 和余数之间的另一个数字,等等,但是第一个数字将有更大的机会“抓住”更多。


这是标准解决方案。它与劳伦斯·贡萨尔维斯的答案类似,但比该答案有两个优点。

  1. 它是统一的:4 个正整数加起来为 40 的每个组合都有相同的可能性提出这个方案。

and

  1. 很容易适应其他总计(7 个数字加起来为 100 等)
import random

def constrained_sum_sample_pos(n, total):
    """Return a randomly chosen list of n positive integers summing to total.
    Each such list is equally likely to occur."""

    dividers = sorted(random.sample(range(1, total), n - 1))
    return [a - b for a, b in zip(dividers + [total], [0] + dividers)]

输出示例:

>>> constrained_sum_sample_pos(4, 40)
[4, 4, 25, 7]
>>> constrained_sum_sample_pos(4, 40)
[9, 6, 5, 20]
>>> constrained_sum_sample_pos(4, 40)
[11, 2, 15, 12]
>>> constrained_sum_sample_pos(4, 40)
[24, 8, 3, 5]

说明:(1) 4元组之间存在一一对应关系(a, b, c, d)正整数使得a + b + c + d == 40、(2) 整数三元组(e, f, g) with 0 < e < f < g < 40,并且很容易使用后者生成random.sample。对应关系由下式给出(e, f, g) = (a, a + b, a + b + c)朝一个方向,并且(a, b, c, d) = (e, f - e, g - f, 40 - g)反方向。

如果你想非负的整数(即允许0)而不是积极的,那么有一个简单的转换:如果(a, b, c, d)是非负整数,总和为40 then (a+1, b+1, c+1, d+1)是正整数,总和为44,反之亦然。利用这个想法,我们有:

def constrained_sum_sample_nonneg(n, total):
    """Return a randomly chosen list of n nonnegative integers summing to total.
    Each such list is equally likely to occur."""

    return [x - 1 for x in constrained_sum_sample_pos(n, total + n)]

图形化说明constrained_sum_sample_pos(4, 10),感谢@FM。 (稍作编辑。)

0 1 2 3 4 5 6 7 8 9 10  # The universe.
|                    |  # Place fixed dividers at 0, 10.
|   |     |       |  |  # Add 4 - 1 randomly chosen dividers in [1, 9]
  a    b      c    d    # Compute the 4 differences: 2 3 4 1
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

生成总和为预定义值的随机数 的相关文章

随机推荐