使用C#在24个随机大小的部分中拆分值

Rir*_*iri 10 c#

我有一个值,比如20010.我想在24小时内随机分配这个值.因此,基本上将值拆分为24个大插槽,其中所有插槽都是随机大的.

使用C#解决这个问题的好方法是什么?

mjv*_*mjv 24

随机抽取23(不是24)个数字(不重复),范围为1到20009.在列表中添加0和20010并对这些数字进行排序,每两个连续数字之间的差值为您提供一个时隙值.

也可以通过一次绘制一个值并从"罐"中减去它来进行在线处理,当数量大于剩余量时重新绘制.然而,这种方法可能导致槽的尺寸偏差更大.


dah*_*byk 23

这是使用mjv算法的功能解决方案:

static int[] GetSlots(int slots, int max)
{
    return new Random().Values(1, max)
                       .Take(slots - 1)
                       .Append(0, max)
                       .OrderBy(i => i)
                       .Pairwise((x, y) => y - x)
                       .ToArray();
}

public static IEnumerable<int> Values(this Random random, int minValue, int maxValue)
{
    while (true)
        yield return random.Next(minValue, maxValue);
}

public static IEnumerable<TResult> Pairwise<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TSource, TResult> resultSelector)
{
    TSource previous = default(TSource);

    using (var it = source.GetEnumerator())
    {
        if (it.MoveNext())
            previous = it.Current;

        while (it.MoveNext())
            yield return resultSelector(previous, previous = it.Current);
    }
}

public static IEnumerable<T> Append<T>(this IEnumerable<T> source, params T[] args)
{
    return source.Concat(args);
}
Run Code Online (Sandbox Code Playgroud)

  • 这段代码看起来太聪明了一半.这是艺术吗? (3认同)

Bev*_*van 11

假设您不希望对大小的分布有太多(任何)控制,这里有一种可行的方法(伪代码).

  1. 创建一个包含24个随机值的列表,无论您喜欢什么规模生成
  2. 找到此列表的总和
  3. 通过将24个随机值与总数相比较来创建最终列表

笔记

  • 如果使用浮点运算,则可能会偏离一两个.要避免这种情况,请不要使用缩放来完成最后一个值,而是使用剩余的总数填充它.
  • 如果确实需要更严格地控​​制分布,请使用其他方法生成初始数组,但其余方法无需更改.

  • 双最大值 = 100; var values = new List&lt;double&gt; { 1000, 2000, 3000, 4000, 5000 }; double scalingFactor = maxValue / values.Sum(); var scaledValues = values.Select(itm =&gt; itm * scalingFactor); var scaledValuesSum = scaledValues.Sum(); (2认同)

dah*_*byk 6

这很好玩.受David启发,这里是仅使用LINQ提供的运算符实现mjv的解决方案.由于David的Dictionary键只是一个索引,我们可以使用数组代替Pairwise功能:

var r = new Random();
var a = Enumerable.Repeat(null, n - 1)        // Seq with (n-1) elements...
                  .Select(x => r.Next(1, m))  // ...mapped to random values
                  .Concat(new [] { 0, m })
                  .OrderBy(x => x)
                  .ToArray();

return a.Skip(1).Select((x,i) => x - a[i]);
Run Code Online (Sandbox Code Playgroud)