我希望能够从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的范围重得多?
你会选择一个随机范围然后使用Random.Next()吗?
不,因为这会使较短范围内的数字更重.例如,如果一个范围包含单个数字42
而另一个范围包含10,000个数字,则42
大约50%的时间会生成.
或者你会继续选择随机数,直到你得到一个在每个范围内?
不,因为那不会太有效率.例如,如果第一个范围是[1..3]
第二个范围,则[200,000..200,001]
在这些范围之一中获取数字需要一段时间.
我将Size
在范围上实现一个属性,计算总大小,int
在范围内生成一个index = [0..TotalSize-1]
,然后在索引处选择项目,就好像您的范围中的所有数字都按顺序编号一样.
例如,在您的范围内TotalSize
将是6 + 7 + 12 = 25.首先,我会在该范围内生成一个随机数[0..24]
,比如说15.我会看到它15
落在第三个范围内,所以我会回来21
.
这将使每个范围的重量与其大小成比例.如果您希望为范围指定特定权重,则算法将有所不同:您可以TotalRange
通过将实际大小乘以范围的权重计算等效值,并总计产品.然后,您将生成该加权和的范围内的数字,通过从该随机数向后工作来选择范围,然后除去特定范围的权重以获得该范围中随机项的位置.