我希望能够从 n 可能的范围生成(伪)随机数,范围是x, y
和x < 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的范围?
答案 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
,并总计产品。然后,您将在该加权和的范围内生成一个数字,通过从该随机数向后工作来选择范围,然后除去特定范围的权重以获得该范围内随机项的位置。