# Random number between two numbers without overflowing

486 views
4

I realize this question has been asked countless times, but it seems that every answer does not take into account overflows.

The suggested method is as follows

``````public static double BoundedNext( double min, double max )
{
var random = new Random( Guid.NewGuid().GetHashCode() );
return ( random.NextDouble() * ( max - min ) ) + min;
}
``````

In just about every single case, this works as it should. However, it does not properly handle cases where an overflow occurs, such as `BoundedNext(Double.MinValue, Double.MaxValue)`. The issue becomes even trickier in languages like C#, where an overflowed `double` equates to `-/+ infinity`.

The simple solution would be to just use a larger type, but I would like a solution that is able to produce a random number between two numbers, for each explicit type, that can handle overflow cases.

11

There is a nice solution for this, as your question is well in place, I will share it with you, as I always keep it in my backlog files just in case:

``````  static Random random = new Random();

// Note, max is exclusive here!
public static List<int> GenerateRandom(int count, double min, double max)
{

if (max <= min || count < 0 ||
// max - min > 0 required to avoid overflow
(count > max - min && max - min > 0))
{
// need to use 64-bit to support big ranges (negative min, positive max)
throw new ArgumentOutOfRangeException("Range " + min + " to " + max +
" (" + ((Double)max - (Double)min) + " values), or count " + count + " is illegal");
}

// generate count random values.
HashSet<int> candidates = new HashSet<int>();

// start count values before max, and end at max
for (double top = max - count; top < max; top++)
{
// May strike a duplicate.
// Need to add +1 to make inclusive generator
// +1 is safe even for MaxVal max value because top < max
if (!candidates.Add(random.Next(min, top + 1))) {
// which could not possibly have been added before.
}
}

// load them in to a list, to sort
List<int> result = candidates.ToList();

// shuffle the results because HashSet has messed
// with the order, and the algorithm does not produce
// random-ordered results (e.g. max-1 will never be the first value)
for (int i = result.Count - 1; i > 0; i--)
{
int k = random.Next(i + 1);
int tmp = result[k];
result[k] = result[i];
result[i] = tmp;
}
return result;
}

public static List<int> GenerateRandom(int count)
{
return GenerateRandom(count, 0, Double.MaxValue);
}
``````

This solution was written in `Int64` so I tried to adopt it for `double` as much as I could for you. Take it and revise it for your needs.

• Please note the comment suggesting what is required to avoid overflow

posted this