int count = 10;
Random random = new Random();
int[] integers = new int[count];
long sum = 0;
for (int i = 0; i < count; ++i)
{
integers[i] = random.Next();
sum += integers[i];
}
double[] doubles = new double[count];
for (int i = 0; i < count; ++i)
doubles[i] = (double)integers[i] / sum;
Console.WriteLine(string.Join("\n", doubles));
Console.WriteLine(doubles.Sum());
static double[] Generate(int count)
{
var result = new double[count];
var max = 1.0;
for (int i = 0; i < count - 1; i++)
{
result[i] = rnd.NextDouble() * max;
max -= result[i];
}
result[count-1] = max;
return result;
}
我们生成 N个任意非负数。
我们计算它们的总和。
我们除以这个数量。
实现示例:
random.Next()返回一个非负随机整数。为了累积总和,我们采用
long- 变量来避免溢出。除以预生成数字的总和的选项不会给出结果的均匀分布,因为均匀分布的值的总和本身并不是均匀分布的。并且通常暗示了此类问题中结果的均匀分布。
更适合分布的解决方案是
N-1在范围内生成非递减的均匀分布随机数[0, 1]r 1 ≤ r 2 ≤ r 3 ≤ ... ≤ r N-1
然后将 r 0 = 0 和 r N = 1 并将邻居中的成对差异作为所需的数字
r 1 - r 0 , r 2 - r 1 , r 3 - r 2 , ..., r N - r N-1
在 C++ 中
rnd-Random此外,如果对于这样的生成至关重要,则可以对数组进行混洗,平均而言,下一个值变得小于前一个值。简单的混合示例:
result.OrderBy(x => rnd.Next()).ToArray();好吧,既然没有限制,那么最原始的解决方案:一个数组,其中第一个元素为 1,其余为 0。
更新:补充说明许多零是不可取的。因此,该解决方案是不合适的。
选项2:用值1/n填充数组:
这里有一个问题:由于除法时的舍入误差,总和可能不会收敛。为了使总和收敛,我们补偿第一个元素:
其中一个想法是创建大整数,然后将它们除以 1000。这将形成一个小数数组 =) 要执行的操作,直到所有元素的总和等于 1。每个形成的数字需要检查:是否符合条件(应小于差 1 和数组剩余元素之和)。