如何从多个可能的范围中获取单个随机数?

时间:2013-12-26 20:16:00

标签: c# random

我希望能够从 n 可能的范围生成(伪)随机数,范围是x, yx < y。例如,执行此代码:

for(int i = 0; i < 10; i++)
{
    Console.Write(Random.NextRanges(new Range(1, 6), new Range(10, 16), new Range(20, 31)) + " ");
}

会产生类似的东西:

3 12 5 22 1 27 29 5 10 24

方法NextRanges的签名是:

public static int NextRanges(params Range[] ranges)

Range定义为:

public struct Range
{
    public int X;
    public int Y;

    public Range(int x, int y)
    {
        if (x >= y) throw new ArgumentException("x must be less than y.");
        X = x;
        Y = y;
    }
}

我唯一不确定的是如何实现NextRanges,最有效的方法或最随机的方式(我知道随机可能有时会很棘手)。您会选择随机Range,然后使用Random.Next()吗?或者你会继续选择随机数,直到你得到一个在每个范围内的数字?

例如,是否也可以对范围进行加权,使得0-100的范围远远大于100-102的范围?

1 个答案:

答案 0 :(得分:14)

  

你会选择一个随机范围,然后对它使用Random.Next()吗?

不,因为这会使较短范围的数字更重。例如,如果一个范围包含一个数字42而另一个范围包含10,000个数字,则大约50%的时间会生成42

  

或者你会继续选择随机数,直到你得到一个在每个范围内?

不,因为那样效率不高。例如,如果第一个范围是[1..3]而第二个范围是[200,000..200,001],那么获取其中一个范围内的数字需要一段时间。

我会在范围上实现Size属性,计算总大小,在int范围内生成index = [0..TotalSize-1],然后在索引处选择项目,就像所有数字一样在您的范围内按顺序编号。

例如,在您的范围TotalSize中,6 + 7 + 12 = 25。首先,我会在[0..24]范围内生成一个随机数,比如15。我会看到15落在第三个范围内,所以我会返回21

这将使每个范围的权重与其大小成比例。如果您希望为范围指定特定权重,则算法会有所不同:您可以通过将实际大小乘以范围的权重计算等效的TotalRange,并总计产品。然后,您将在该加权和的范围内生成一个数字,通过从该随机数向后工作来选择范围,然后除去特定范围的权重以获得该范围内随机项的位置。