如何在C#中使用固定总和生成2个数字之间的随机数字序列?

时间:2017-12-10 14:06:22

标签: c# math random numbers

所以我试图生成一个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 ...

最好的方法是什么?

3 个答案:

答案 0 :(得分:1)

此方法创建n个均值为sum/count的值,这些值会因定义的值而变化。在每个循环中minmax的不断计算实现了最后一个值(在这种情况下实际上是数组的第一个),并没有那么多。虽然,它仍然不完美,特别是当你有一个小的平均值和一个大的方差。但也许这会给你一个开始。

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,...,)。

  1. 如上所述生成序列
  2. 在区间[0; k]中生成随机数rd(您需要选择k)。
  3. an-=rd
  4. 每个aiai+=rd/(n-1)
  5. 如果我做得很好,总和不应该改变,你有一个更统一的序列。 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;
}