所以我试图生成一个N个数字的序列,其中和将是S.
现在我正在这样做:
float baseamount = (float)(amount / norders) * 0.8f;
float secondamount = amount / norders;
然后在这两个数字之间生成N个随机数。
然而,这会产生非常均匀的数字范围,而我想要更多随机化,例如,而不是(sum = 200,n = 10):
16.92321 17.49378 16.26426 16.03404 16.12497 17.53131 18.10094 16.86982 17.0831 16.06921
我更喜欢:
12.345 17.4534 19.3542342 11.345345 18.4325235 14.4353245 ...
最好的方法是什么?
答案 0 :(得分:1)
此方法创建n个均值为sum/count
的值,这些值会因定义的值而变化。在每个循环中min
和max
的不断计算实现了最后一个值(在这种情况下实际上是数组的第一个),并没有那么多。虽然,它仍然不完美,特别是当你有一个小的平均值和一个大的方差。但也许这会给你一个开始。
public static IEnumerable<double> GetValues(int count, double sum, double variance)
{
var rnd = new Random();
var values = new double[count];
var remainingSum = sum;
for (int i = count-1; i > 0; i--)
{
var min = (int)(remainingSum / (i+1) - variance / 2) * 1000;
var max = (int)(remainingSum / (i+1) + variance / 2) * 1000;
var rndVal = rnd.Next(min, max) / 1000.0;
values[i] = rndVal;
remainingSum -= rndVal;
}
values[0] = remainingSum;
return values;
}
答案 1 :(得分:0)
生成(n-1)个不大于sum / n的随机数并跟踪部分和(让我们称之为PS)。 然后,你的最后一个号码是(sum-PS)。
希望这有帮助。
编辑:当然,你的最后一个数字会比之前的数字特别大。我将研究一个更加面向数学的解决方案来解决这个问题(或者至少我会尝试)。与此同时,我发现了一个“修复”:(让我们称随机序列a0,...,)。
rd
(您需要选择k)。an-=rd
ai
:ai+=rd/(n-1)
。如果我做得很好,总和不应该改变,你有一个更统一的序列。 k必须由您选择,具体取决于您希望序列的“统一”程度。
答案 2 :(得分:0)
static Random random = new Random();
float[] Generate(float sum, int n, float minLimit)
{
float max = sum - minLimit * n;
float[] arr = new float[n];
for (int i = 0; i < n - 1; i++)
{
arr[i] = (float)random.NextDouble() * max;
}
arr[n - 1] = max;
Array.Sort(arr);
for (int i = n - 1; i > 0; i--)
{
arr[i] = arr[i] - arr[i - 1] + minLimit;
}
arr[0] += minLimit;
return arr;
}