【问题标题】:How to generate a random sequence of numbers between 2 numbers with a fixed sum in C#? [closed]如何在 C# 中生成具有固定总和的 2 个数字之间的随机数字序列? [关闭]
【发布时间】:2018-05-24 04:36:27
【问题描述】:

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

解决这个问题的最佳方法是什么?

【问题讨论】:

  • 现在才看
  • 由于这些数字是相互依赖的,你不能使用一些独立的随机变量来解决这个问题。
  • 你承认这是不可能的吗?总和 = 200,n = 10,每个数字的平均值为 20。因此,随机抽样会产生一些高于 20 和一些低于 20 的数字,以保持总和为 200。根据您的要求,您希望数字清楚地被 20 覆盖,所以所有这些都将小于 20,并且 NO WAY sum 将设置为 200。
  • 即使在您的示例中,总和也远未达到 200

标签: c# math random numbers


【解决方案1】:
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;
}

【讨论】:

    【解决方案2】:

    生成 (n-1) 个不大于 sum/n 的随机数并跟踪部分和(我们称之为 PS)。 然后,您的最后一个数字是(总和 - PS)。

    希望这会有所帮助。

    编辑:当然,最后一个数字会比之前的所有数字都大得多。我将研究一个更面向数学的解决方案来解决这个问题(或者至少我会尝试)。与此同时,我想到了一个“修复”:

    (我们称随机序列为 a0,...,an)。

    1. 如上所述生成序列
    2. 在区间[0;k]内生成一个随机数rd(需要选择k)。
    3. an-=rd
    4. 对于每个aiai+=rd/(n-1)

    如果我做得很好,总和应该不会改变,你有一个更统一的顺序。 k 必须由您选择,具体取决于您希望序列有多“均匀”。

    【讨论】:

      【解决方案3】:

      此方法创建 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;
          }
      

      【讨论】:

      • 使用多个 Random 实例不是一个好主意。如果它们同时创建,Next() 的结果将是相同的。测试:for (int i = 0; i &lt; 9; i++) { Console.WriteLine(new Random().Next()); }
      猜你喜欢
      • 2014-07-25
      • 1970-01-01
      • 1970-01-01
      • 2020-08-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多