- Home /
Generate a Random number between two ranges
Hi, so basically, the thing I need is to generate, for example a random number between two ranges...
For example from -15 to 15, but excepting, from -7 to 7... So, the accepted numbers would be: -15, -14, -13, -12, -11, -10, -9, -8, -7... 7, 8, 9, 10, 11, 12, 13, 14 and 15...
So, how can I do this using Random.Range? I want to get this number in a only call because I need it for a coordinate, for make object stay, not so far, but not so near...
Thanks in advance.
Bye.
Answer by Bunny83 · Jul 22, 2014 at 11:56 PM
Well, all you need is some simple math like this:
// C#
int num = Random.Range(7,25); // 7 .. 24 since 25 is exclusive.
if (num > 15)
num = 9-num; // (9-16) .. (9-24) == -7 .. -15
// num == 7 .. 15 or -15 .. -7
edit
I have the feeling i should add some explanation. First of all you should figure out how many possible numbers you want to get in total. 7 to 15 and -15 to -7 are 9 values each. So there are 18 possible values. The Random.Range goes from 7 to 24 which has a range of 18 values. The lower 9 values is already our positive range (7 to 15) if we get a value larger then 15 we map the upper 9 values (16 to 24) down to (-7 to -15)
A more general approach could be something like this:
// C#
public struct Range
{
public int min;
public int max;
public int range {get {return max-min + 1;}}
public Range(int aMin, int aMax)
{
min = aMin; max = aMax;
}
}
public static int RandomValueFromRanges(params Range[] ranges)
{
if (ranges.Length == 0)
return 0;
int count = 0;
foreach(Range r in ranges)
count += r.range;
int sel = Random.Range(0,count);
foreach(Range r in ranges)
{
if (sel < r.range)
{
return r.min + sel;
}
sel -= r.range;
}
throw new Exception("This should never happen");
}
In this example the "Ranges" are max-inclusive. So in your case you would do:
int val = RandomValueFromRanges(new Range(-15,-7), new Range(7,15));
If you want the ranges to be max-exclusive you have to remove the "+1" in the range property. In this case you would have to do this to get the same result:
int val = RandomValueFromRanges(new Range(-15,-6), new Range(7,16));
Depending on your usecase when you want a relative offset with a min and max distance you would use a vector, a random direction and then just scale it between your min and max value.
public static Vector2 RandomXYOffset(float aMin, float aMax)
{
float angle = Random.value * Mathf.PI * 2;
Vector2 dir = new Vector2(Mathf.Cos(angle), Mathf.Sin(angle));
return dir * Random.Range(aMin, aMax);
}
The offset is of course not grid aligned but since you didn't said your actual usecase we can only guess.
7, 8, 9, 10, 11, 12, 13, 14, ...
6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
Your option isn't a bad solution, but, it has two ranges, where numbers match (I think that It is the interesection, the thing I mean), and those numbers has more probability (big in small ranges and small in big ranges), than others... (The numbers I mean are, 7, 8, 9, 10, 11, 12, 13, 14)... They appear in the ranges 2 times, ins$$anonymous$$d of one, only those that don't repeat...
@Ikillnukes: I have no idea what you talk about. The random numbers are distributed equally across the whole range, so i don't get your complaint about probability. $$anonymous$$y ranges don't overlap at all. Are you sure you actually understand the solution? ;)
Thanks for the long explanation, the problem I have is that I'm spanish, and well, this is a more complex english, to the one I'm get used to... But, well, I think I got it... (But, to be honest, you save the day with that class, thanks...)
Sorry for be a bad student, $$anonymous$$cher Bunny ;)
Answer by calebheale · Jul 23, 2014 at 12:59 AM
int rnd = Random.Range(7, 16) * (Random.Range(0, 2) == 0)? 1:-1;
This of course would work if you use Random.Range(0, 2) == 0 in your ternary operator (since the second parameter is exclusive), however it does only work with symetric ranges.
Answer by Kiwasi · Jul 23, 2014 at 12:17 AM
A more versatile option would be to put all the random numbers in a data container (array or List). Then pick an int for the index
// Change this as appropriate
int[] numbers = new int[5] {1, 2, 3, 4, 5};
// Use this line to get a random number
int myRandom = numbers[Random.Range(0,numbers.length)];
Or maybe a list of two length array :P (For indicate the ranges and the $$anonymous$$ and max of that ranges)
Answer by Epicwolf · Jul 22, 2014 at 11:46 PM
Using your example, you could create a loop that gets a random number between -15 to 15, and then checks if the number is between -7 and 7. If it is between -7 and 7, you would get a new random number. Once a number is found that fits the qualifications, exit the loop.
As far as I'm aware, this is not possible in one call, unless you are lucky and get a number that works right away. ("one call" meaning one Range call)
Okey, thanks, this would be an option, but I need more ideas ;)
This is a good solution if the change of the random generator returning a valid number is good.
@Bored$$anonymous$$ormon: good solution? Not really. That's the worst implementation possible. You can't predict the runtime of such an algorithm. Depending on the ratio between good and bad numbers it could take a huge amount of cycles.
Bunny83 is right... But well, how many cycles are we talking about? $$anonymous$$aybe 100, or 200? They are not too many but, in group they can produce lag...
And... One call for example, for me, is a function that returns that magic number...
Well, as i said it depends on the good-bad-number ratio. In this case we have a 50 / 50 ration (since we have 18 good and 18 bad numbers). Statistically you only have to pick one new value, but peaks due to bad luck could be much worse. Such algorithms are in general hard to debug and easily can lead to crashes if the ranges are picked wrong.
Answer by aled96 · Jul 23, 2014 at 09:01 AM
You can do this:
int n1[2]; n1[0] = Random.Range(-15,-6); n1[1] = Random.Range(7,16);
The random number ---> n1[Random.Range(0,2)];
Just be careful, this will not produce a true random result if the ranges are not equally sized.
Ahahah yes sorry :) i interpretate the question in a wrong way :) it caused by my english level.. i will correct