Choosing Random Numbers
NOTE: This article has been updated here, due to errors discovered by NSurveyor.
ActionScript 1.0 and 2.0 provide two ways to pull a random number from thin air: the random() function and the static Math.random() method. Of these, the random() function is the older (available since Flash 4) and is the “easier to use,” according to a number of developers. But keep in mind, it’s not the officially recommended way to go.
random()
The function works like this: say you want a random number between one and ten, including either extreme. The function returns an integer value between zero and one less than the supplied parameter, so if you want your number to be among the set 1, 2, 3, …, 10, then pass in ten and add one to the result.
var rand:Number = random(10) + 1;
There you have it. The rand variable now contains an integer between (possibly including) one and ten. How does that work, again? The function returns a value between zero and one less than the supplied parameter, so supplying ten return any number in the set 0, 1, 2, …, 9, which added to one gives you the range you want.
Okay. Well and good. But the random() function was deprecated as of Flash 5. That means it’s still “legal” to use, but the official recommended best practice is to use Math.random() instead.
Note: Practically speaking, in all these years, I’ve only seen support dropped for a single deprecated term, but it does happen. Long ago, you could concatenate strings with the add operator, but Flash Player 8 and higher no longer support the practice. Any SWFs out there that still use add — who knows how many there are? — simply fail when the Player hits that operator, provided those SWFs are viewed in Flash Player 8 or higher.
Math.random()
This is a static method, which means you don’t reference a class instance when calling it; you reference the class name itself. Math.random() returns a non-integer value between zero and one. That’s right, zero and one — including possibly zero (which, I suppose, would be an integer; okay, okay, there’s always an exception!). If you want a random number between one and ten in this case, you’ll have to multiply the return value by nine, round the answer down, then add one to the result. Sounds complicated, I realize, but let’s see it in action.
var rand:Number = Math.round(Math.random() * 9) + 1;
Let’s see what’s going on, here, working from the inside out. At the very center, Math.random() provides a number between zero and one (including, possibly zero). Typical results might be any of the following …
0.568371209315956
0.186107741203159
0.643053698353469
0.542485995218158
0.771115215960892
… note that zero even is simply not a likely result.
Multiplied by nine, the above list might be any of these:
7.05780873075128
2.09764451393858
8.10042055277154
0.43995537701994
6.56350261252373
This expression, Math.random() * 9, is run through Math.round() to crunch those floats into integers. Finally, this combined expression, Math.round(Math.random() * 9), is added to one, to bump everything up a notch. Zeroes become ones, ones twos, etc., and nines become tens. Thus the desired range of “between one and ten” is achieved.
Ranges outside the set “between one and …”
What if you want a random number between -5 and 5? Easy enough. The above approach hints toward a generic formula that provides the answer. Take a look at this custom function:
function randomRange(min:Number, max:Number):Number {
return Math.round(Math.random() * (max - min + 1)) + min;
}
The inner expressions have changed a bit, but the principle is the same. The difference between the upper end lower ends, plus one, provide the value to multiply with Math.random(). Instead of adding one to the result, add min (because the lower end may not be one).
Flipping a coin
Heads or tails? To determine a random number between one and two, simply round the return value of Math.random(). But do yourself a favor and think in terms of the double meanings certain numbers have. In ActionScript (and most programming languages), one and zero correspond neatly to true and false. Actually, technically speaking, zero corresponds to false and any other number corresponds to true, but it’s easy to remember one and zero.
The expression Math.round(Math.random()) returns either 1 or 0. Use it to answer any yes-or-no question randomly!
October 4th, 2006 at 10:12 pm
I was just about to comment about how sometimes people mess up the distribution of the randomness until I realized you, David, have made the same mistake! A lot of the above code is flawed. You are not getting even distribution where you are using Math.round()!
var rand:Number = Math.round(Math.random() * 9) + 1);
Math.round(Math.random()*9+1) is not evenly distributed. Consider when that value is:
1…
0<=Math.random()*9<0.5.
For values, x, greater than 1 and less than 10…
x-0.5<=Math.random()*9<x+0.5.
10…
8.5<=Math.random()*9<9.
As you can see, the two ends, 1 and 10 are half as likely to occur with the above code. We can also show this experimentally:
var x = [0,0,0,0,0,0,0,0,0,0];
for(var i=0;i<1000;i++){
var r = Math.round(Math.random() * 9+1)-1;
x[r]++;
}
trace(x);
To remedy, use Math.floor (or ceil):
var rand:Number = Math.floor(Math.random()*10+1)
or even
Math.floor(Math.random()*10)+1
The same applies to your between code (which also can exceed the max by 1!). The correct code is:
function randomRange(min:Number, max:Number):Number {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
Besides that, you can manipulate the randomness to get say either a 1 or -1:
Math.floor(Math.random())*2-1
In fact, I’ve seen this used several times in the forums… like Byron Canfield, Laiverd.COM, and I’m quite sure kglad has used it as well.
October 5th, 2006 at 12:50 am
NSurveyor,
Ahh, man! Thank you.
For real, thanks for that input! As soon as I hit the Publish button on this post, a thought flitted across my brain. The thought said, “Hey, wait a minute … the lowest and highest numbers are only half as likely to be chosen …” — and you’ve already pointed out the issue in detail, as well as the correction.
I hate to admit it, but I was simply too tired (yes, even at 9PM!) to go back and rethink/rewrite the post. But I should have. You’re absolutely right.
Humble pie makes a good meal.
October 14th, 2006 at 8:28 pm
This has been infinitely helpful, I thoroughly appreciate both your efforts. I am just sure a lot more of us starting web developers applaud bits like this, so I express this on behalf of all those who didn’t have time to.
Thank You.
October 15th, 2006 at 11:28 am
Denis,
Thanks! Glad to hear you enjoy the content. In the case of this particular article, make sure you read the updated companion piece.
February 9th, 2007 at 2:10 am
Suppose, If my first five numbers are 88,73,95,68,55 Between 1 to 100.
What will be possible next 5 numbers for me…..??
February 9th, 2007 at 9:16 am
Gs,
If the next five numbers are random, then they would be five numbers between (or including) 1 and 100.
February 9th, 2007 at 1:53 pm
David,
Yeah Next five numbers also random number between 1 to 100…but
what are that possible numbers…
Is there any equation or formula to find next 5 numbers by calculating
or using given five numbers…
February 9th, 2007 at 1:56 pm
Gs,
Didn’t we cover this?
Sure.
If you can think of an equation to generate a specific sequence of numbers, it can almost certainly be codified in ActionScript 2.0. But by definition, then, the sequence wouldn’t be random, so maybe I’m misunderstanding your question.
August 23rd, 2007 at 6:39 pm
I think I know what Gs is getting at.
I recall in True BASIC, if you tried using random calls without “randomize” you would get the same numbers every time you ran the program.
When you think about it, how is it possible to generate a truly random number? AFAIK, they aren’t… rather they are pseudorandom numbers. I believe the algorithm uses a timer and some complex mathemetical formula.
If for example, the “mathematical formula” were a simply a polynomial, then we can determine the polynomial and all subsequent “random” numbers, given one more than the degree of the polynomical. Example, if random tells us f(0) = 2, f(1) = 3, f(2) = 6, we can determine that f(x) = x^2+2, assuming we are dealing with a 2nd degree polynomial. And then generate the random numbers manually.
But anyways, I think the algorithm would be too complex to foretell the random numbers, nor would there ever be an opportunity to exploit it.
October 8th, 2007 at 10:38 am
Yes, thanks for taking the time to write this. I wrote a yahtzee game using math.round and I noticed 1’s and 6’s were hard to get, and thus the distribution at the upper and lower bounds of my range were 1/2 as likely to occur.
Thanks for all the contributions!!!
October 8th, 2007 at 1:37 pm
Tim,
You’re welcome!
Glad to help.