这个问题以前有人问过,但我从来没有真正看到一个好的答案。
我想生成 8 个随机数,总和为 0.5。
我希望每个数字都是从均匀分布中随机选择的(即,下面的简单函数将不起作用,因为数字不会均匀分布)。
def rand_constrained(n,tot): r = [random.random() for i in range(n)] s = sum(r) r = [(i/s*tot) for i in r] return r
代码应该是通用的,这样您就可以生成 N 个统一的随机数,总和为 M(其中 M 是正 float )。如果可能的话,您能否也解释一下(或用图表显示)为什么您的解决方案会在适当的范围内均匀地生成随机数?
未命中的相关问题:
Generate multiple random numbers to equal a value in python (当前接受的答案不统一——另一个统一的答案只适用于整数)
Getting N random numbers that the sum is M (Java中的相同问题,目前接受的答案完全错误,也没有统一分布的答案)
Generate N random integers that sum to M in R (同样的问题,但在 R 中具有正常的——不均匀的——分布)
非常感谢任何帮助。
最佳答案
你要求的似乎是不可能的。
但是,我会重新解释您的问题,使其更有意义并且可以解决。您需要的是七维超平面 x_1 + x_2 + ... + x_8 = 0.5
上的概率分布。由于超平面的范围是无限的,所以在整个超平面上均匀分布是行不通的。您可能(?)想要的是所有 x_i>0
所在的超平面 block 。该区域是一个单纯形,是三角形的推广,单纯形上的均匀分布是狄利克雷分布的特例。
您可以找到狄利克雷分布维基百科文章的这一部分,string cutting ,特别有启发性。
实现
维基百科文章在 Random Number Generation 中给出了以下 Python 实现部分:
params = [a1, a2, ..., ak]
sample = [random.gammavariate(a,1) for a in params]
sample = [v/sum(sample) for v in sample]
您可能(?)想要的是所有 ai=1
导致单纯形上均匀分布的情况。这里 k
对应于您问题中的数字 N
。要使样本总和为 M
而不是 1
,只需将 sample
乘以 M
。
更新
感谢 Severin Pappadeux 指出 gammavariate 在极少数情况下可以返回无穷大。这在数学上是“不可能的”,但在 float 方面可能会作为实现的产物出现。我对处理这种情况的建议是在首次计算 sample
之后检查它;如果 sample
的任何分量为无穷大,则将所有非无穷大分量设置为 0,并将所有无穷大分量设置为 1。然后在计算 xi
时,结果像 xi=1, all other x's=0
或 xi=1/2, xj=1/2, all other x's=0
将产生统称为“corner samples”的结果”和“边缘样本”。
另一种极低概率的可能性是 gammavariates 的总和溢出。我猜想我们可以遍历整个底层伪随机数序列而看不到这种情况发生,但理论上这是可能的(取决于底层伪随机数生成器)。这种情况可以通过重新缩放 sample
来处理,例如,将 sample
的所有元素除以 N
,在计算 Gamma 变量之后但在 x 之前被计算。就个人而言,我不会打扰,因为可能性很小;其他原因导致程序崩溃的概率更高。
关于python - 生成总和为 M 的 N 个均匀随机数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30658932/