I would like to be able to generate a (pseudo)random number from n possible ranges, where a range is x, y
and x < y
. For example, executing this code:
for(int i = 0; i < 10; i++)
{
Console.Write(Random.NextRanges(new Range(1, 6), new Range(10, 16), new Range(20, 31)) + " ");
}
will produce something like:
3 12 5 22 1 27 29 5 10 24
The signature of the method NextRanges
is:
public static int NextRanges(params Range[] ranges)
And Range
is defined as:
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;
}
}
The only thing I'm not sure on is how to implement NextRanges
, what the most efficient way or the most random way is (I know random can be tricky sometimes). Would you choose a random Range
and then use Random.Next()
on that? Or would you keep choosing random numbers until you got one that was within each of the ranges?
Is it also possible to weight the ranges so that a range of 0-100 has far more weight than a range of 100-102, for example?
Would you choose a random Range and then use Random.Next() on that?
No, because that would give numbers in shorter ranges more weight. For example, if one range contains a single number 42
and the other range contains 10,000 numbers, then 42
would be generated roughly 50% of the time.
Or would you keep choosing random numbers until you got one that was within each of the ranges?
No, because that would not be the too efficient. For example, if the first range is [1..3]
and the second range is [200,000..200,001]
, getting a number in one of these ranges would take a while.
I would implement a Size
property on the range, compute the total size, generate an int
in the range index = [0..TotalSize-1]
, and then picked the item at the index as if all numbers in your ranges were numbered sequentially.
For example, in your ranges TotalSize
would be 6+7+12=25. First, I would generate a random number in the range [0..24]
, say, 15. I would then see that 15
falls in the third range, so I'd return 21
.
This would give each range a weight proportional to its size. If you would like to assign specific weights to your ranges, the algorithm would be different: you would compute an equivalent of TotalRange
by multiplying the actual size by the weight of the range, and totaling up the products. You would then generate a number in the range of that weighted sum, pick the range by working backward from that random number, and then dividing out the weight of the specific range to obtain the position of the random item in the range.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With