java 随机百分比

2022-09-02 12:12:42

我需要生成n个百分比(0到100之间的整数),以便所有n个数字的总和加起来为100。

如果我只做n次,每次确保参数是100减去之前累积的总和,那么我的百分比是有偏差的(即第一个生成的数字通常是最大的等)。我如何以公正的方式做到这一点?nextInt()


答案 1

有几个答案建议选择随机百分比并取它们之间的差异。正如Nikita Ryback所指出的那样,这不会给出所有可能性的均匀分布;特别是,零的频率将低于预期。

要解决此问题,请考虑从100“百分比”开始并插入分隔符。我将用10展示一个示例:

 % % % % % % % % % % 

我们可以在十一个地方插入一个分隔符:在任何百分之二之间,或者在开头或结尾。所以插入一个:

 % % % % / % % % % % % 

这表示选择四和六。现在插入另一个分隔符。这一次,有十二个地方,因为已经插入的分隔符创建了一个额外的位置。特别是,有两种方法可以获得

 % % % % / / % % % % % % 

在上一个分隔符之前或之后插入。您可以继续该过程,直到您拥有所需数量的分隔符(比百分比数少一个)。

 % % / % / % / / % % % / % % % / 

这对应于 2,1,1,0,3,3,0。

我们可以证明这给出了均匀分布。将100个组成数分成k份数是二项式系数100+k-1选择k-1。即(100+k-1)(100+k-2)...101 / (k-1)(k-2)*...*2*1 因此,选择任何特定组合的概率是其倒数。当我们一次插入一个分隔符时,首先我们从101个位置中进行选择,然后是102,103等,直到我们达到100 + k-1。因此,任何特定插入序列的概率为 1 / (100+k-1)*...*101。有多少个插入序列产生相同的组成?最终组合包含 k-1 分隔符。它们可以按任何顺序插入,所以有(k-1)!产生给定组合的序列。因此,任何特定成分的概率正是它应该有的。

在实际代码中,您可能不会像这样表示您的步骤。您应该能够只保留数字,而不是百分比和除法的序列。我还没有想过这个算法的复杂性。


答案 2

生成具有任何范围的 n 个随机整数(调用它们 ..)。求和你的整数并调用 .您的百分比将为 。a[1]a[n]b[a[1]/b, ..., a[n]/b]

编辑:好点,将结果四舍五入为总和正好100是非三价的。一种方法是将 for in 作为整数,然后随机分配剩余的单位。我不确定这是否会给结果带来任何偏见。a[x]/bx1..n100-(sum of integers)