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)
范围定义为:
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,最有效的方式或最随机的方式(我知道随机可能有点棘手).你会选择一个随机范围然后使用Random.Next()吗?或者你会继续选择随机数,直到你得到一个在每个范围内?
例如,是否还可以对范围进行加权,使得0-100的范围远远大于100-102的范围?
解决方法
Would you choose a random Range and then use Random.Next() on that?
不,因为这会使较短范围内的数字更重.例如,如果一个范围包含单个数字42而另一个范围包含10,000个数字,则大约50%的时间将生成42个数字.
Or would you keep choosing random numbers until you got one that was within each of the ranges?
不,因为那不会太有效率.例如,如果第一个范围是[1..3]而第二个范围是[200,000..200,001],那么在这些范围之一中获取数字将需要一段时间.
我将在范围上实现Size属性,计算总大小,在index = [0..TotalSize-1]范围内生成一个int,然后在索引处选择项目,就好像您的范围中的所有数字都按顺序编号.
例如,在您的范围内,TotalSize将为6 7 12 = 25.首先,我会在[0..24]的范围内生成一个随机数,比如15.然后我会看到15落在第三个范围内,所以我会返回21.
这将使每个范围的重量与其大小成比例.如果您希望为范围指定特定权重,则算法会有所不同:您可以通过将实际大小乘以范围的权重并计算产品总数来计算TotalRange的等效值.然后,您将生成该加权和的范围内的数字,通过从该随机数向后工作来选择范围,然后除去特定范围的权重以获得该范围中随机项的位置.