Avraham Sikirov
Avraham Sikirov

Reputation: 103

Generate random number from 2 different ranges

How can I generate a random number from two different ranges?

For example: one number from 10-20 and 50-60.

I know how to generate a random number from one range (1-13):

Random rnd = new Random();
int num = rnd.Next(1, 13);

Upvotes: 5

Views: 7076

Answers (5)

Jan
Jan

Reputation: 2293

A more general approach would be to make an Extension Method for the Random class in which you add NextFromRanges and NextDoubleFromRanges methods. So it will work for any given number of ranges of any type.
First you need to define a Range class. Make it generic so you can reuse it for different types, not only for example for int ranges but also for double.

/// <summary>The Range class.</summary>
/// <typeparam name="T">Generic parameter.</typeparam>
public class Range<T>
{
    /// <summary>Minimum value of the range.</summary>
    public T Minimum { get; set; }

    /// <summary>Maximum value of the range.</summary>
    public T Maximum { get; set; }

    public Range(T min, T max)
    {
        Minimum = min;
        Maximum = max;
    }
}

public static class RandomExtension
{
    static Random random = new Random();

    public static int NextFromRanges(this Random random, List<Range<int>> ranges)
    {
        int randomRange = random.Next(0, ranges.Count);
        return random.Next(ranges[randomRange].Minimum, ranges[randomRange].Maximum);
    }

    public static double NextDoubleFromRanges(this Random random, List<Range<double>> ranges)
    {
        int randomRange = random.Next(0, ranges.Count);
        double doubleNrRange = ranges[randomRange].Maximum - ranges[randomRange].Minimum;
        return ranges[randomRange].Minimum + random.NextDouble()*doubleNrRange;
    }
}

And then you can use it like this:

    //instantiate a Random generator
    Random random = new Random();

    //define three integer ranges
    List<Range<int>> intRanges = new List<Range<int>>();
    intRanges.Add(new Range<int>(0, 10));
    intRanges.Add(new Range<int>(50, 60));
    intRanges.Add(new Range<int>(100, 110));

    //define three double ranges
    List<Range<double>> doubleRanges = new List<Range<double>>();
    doubleRanges.Add(new Range<double>(0, 5.5));
    doubleRanges.Add(new Range<double>(50, 55.5));
    doubleRanges.Add(new Range<double>(100, 105.5));

    //generate a random number between one of above three ranges
    //it is shown in the Visual Studio - Output window (Ctrl-W,O)
    Console.WriteLine(random.NextFromRanges(intRanges));
    Console.WriteLine(random.NextDoubleFromRanges(doubleRanges));

It will produce:
-random int number between one of the three given int ranges: 0-10, 50-60 and 100-110.
-random double number between one of the three given double ranges: 0-5.5, 50-55.5, 100-105.5

Just like the Next and NextDouble methods the upperbound is exclusive.

You'll now have two extra methods added to the standard Random class: enter image description here

Upvotes: 2

Robert McKee
Robert McKee

Reputation: 21492

int num = rnd.Next(1, 3)==1 ? rnd.Next(10, 21) : rnd.Next(50,61);

or

int num = rnd.Next(10, 32);
if (num>20) num+=29;

or just for fun (don't use with large ranges, and runs slow anyhow):

var ranges=new []{ Tuple.Create(10,20), Tuple.Create(50,60)};
var rnd=new Random();
var possible=ranges.Select(x=>Enumerable.Range(x.Item1,x.Item2-x.Item1+1))
  .SelectMany(x=>x)
  .Distinct();
var num=possible.Skip(rnd.Next(0,possible.Count())).First();

Upvotes: 6

Mitul&#225;t b&#225;ti
Mitul&#225;t b&#225;ti

Reputation: 2166

You could write your own Random class. Where you rewrite the Next method with a new overload that would accept an even number of arguments.

It would look something like:

Random.NextFromGroups(10, 20, 50, 60, 100, 110);

Where the number-pairs mean the ranges.

Signature:

int NextFromGroups(params int[]);

and it would throw an Exception when it gets an odd number of arguments.

Upvotes: -2

Jan D&#246;rrenhaus
Jan D&#246;rrenhaus

Reputation: 6717

You are generating 22 distinct random numbers, 10-20 and 50-60. So do that first:

int randomNumber = rnd.Next(0, 22);

Now, you have random numbers from 0 to 21.

Add ten:

randomNumber += 10;

Now, you have random numbers between from 10 to 31.

Add 29 for all numbers >= 21:

if (randomNumber >= 21) {
    randomNumber += 29;
}

Now, you have random numbers from 10 to 20, and from 50 to 60.

Upvotes: 2

Sean
Sean

Reputation: 8807

Remember for the Next method, the lower bound is inclusive, while the upper bound is exclusive. How about:

var rand = new Random();
var num1 = rand.Next(10, 21);

var num2 = rand.Next(50, 61);

var myNum = rand.Next(0, 2) == 1 ? num1 : num2;

Upvotes: 2

Related Questions