
bell curves
I checked the previous posts on this subject and my head is swimming now!
What I want to do is have a number generated randomly but conforming to the constrainsts of a bellcurve. For example, on a scale from 1 to 10 I would like to have more 5's returned than 1s and 10s.
This math is just out of my league...
Thanks

Senior Member
Here's one way to do it.
This is off the top of my head. I'm simulating the actions of a bellcurve exhibit I saw at a science museum, some years ago.
A ball was dropped from the topcenter, and hit a row of pegs. The peg would cause the ball to go left or right with equal probability. Then it would hit another row of pegs, which would cause it to go left or right, and so on...
This code is the algorithmic equivalent:
Code:
r = 5; // start in center
// go left/right 5 times with equal probability
for (var i = 0; i < 5; ++i) {
r += random(2)? 1 : 1;
}
The maximum and minimum values for r are
(5+1+1+1+1+1 and 511111), or 10  0 which are both very unlikely. Most likely, r will be close to the center (5).
Note that the range of r is 010 and not 110, as in your request.
 Jim
Last edited by jbum; 03152004 at 05:15 AM.

so close
that method is the closest so far but it doesn't allow me to get a result of 1,3,5...any odd number on a range of say 110.
Any other ideas???

Senior Member
NOTE: I correct an error in this post  'r' was being miscalculated in the first example  jbum.
Two questions:
1) I'm not sure what you mean by odd numbers  are you saying you don't want 'r' to ever be an even number? Just the numbers 1,3,5,7,9 ? that's what the following example does, but I'm not sure that's what you mean...
Code:
// this will produce the values 1,3,5,7,9 with bell curve distribution
var r = 2;
for (var i = 0; i < 2; ++i) {
r += random(2)? 1 : 1;
}
r = r*2 + 1;
2) If you're trying to restrict the results to the range 110, you have a problem, because it contains an even amount of numbers  the number that is in the exact center is 5.5, and not 5.
Assuming you want integer values, you're going to have an imbalance, because there are 4 digits smaller than 5 and 5 digits larger than 5.
So how do you want to deal with the imbalance?
 jim
Last edited by jbum; 03152004 at 05:16 AM.

I do want all the numbers in the range to be returnable.
...what I meant before was  starting with r=5 and adding 5 negative 1's or positive 1's in any combination you couldn't ever add up to 1,3,5 etc.
As far as the exact center point, I am more than happy to have the range be odd so there's an exact center number. Say 1 to 11. I am also fine with 0 to 10 if that works out.
Thanks for working though this with me. I know it's really hard to write an explanation of what you want done, and even harder to read someone elses!

I see what you mean not being able to get even numbers. Why don't you just start with 10, and do your add 1 subtract 1 thing till you get odd numbers from 020. Then just 1=1 3=2 5=3....if you see what i mean. Now you have 110 including evens.

Hmm, a nice and simple take on the subject jbum.
But here's what I was taught, and it can be used for any "probability density distribution" ( Don't worry, just big words meaning what type of numbers are spat out ). It was called the ( Inverse ) Transform Method.
Basically, if you can put the "line" that you want the random numbers to be under ( in this case shaped like a bell curve ) into an analytical form ( like y = f(x) ) and it has as inverse function, then you can use that inverse, stick in a ( uniform ) random number, and it'll be scaled to the right amount. It's a bit complicated and I can't describe it very well. I think it would be over the top in most cases anyway.
The other simple version, albeit a bit inefficient, is a simple "look and throw away if wrong" approach. Pick 2 ( uniform ) random numbers, x and y. Plug those into the curve formula, and if the point you chose was under the curve, great, keep x. Otherwise throw it away and check again. It's the fact you need 2 numbers and you might throw some away that makes it inefficient, but unless you're doing some major monte carlo method simulations then it's no worries!

Senior Member
Ah, good call  I didn't notice that behavior.
Here's a way to get past that problem. It's twice as inefficient, because I jump up and down in increments of .5.
Here's the function:
Code:
// returns R in which 0 >= R <= max,
// with Guassian distribution (bell curve)
function GaussRandom(max)
{
var r = max/2;
for (var j = max; j > 0; j) {
r += Math.random().5;
}
return Math.round(r);
}
and here's a sample test:
Code:
ary = new Array(10);
for (i = 0; i < 10000; ++i) {
var r = GaussRandom(10);
ary[r]++;
}
for (i = 0; i <= ary.length; ++i)
trace(i + ": " + ary[i]);
and here are the test results for 10000 tries (looks pretty bellcurvy to me)
:
Code:
0: 0
1: 0
2: 19
3: 461
4: 2454
5: 4116
6: 2450
7: 476
8: 23
9: 1
10: 0
This routine is accurate, the problem is that it is inefficient, because it loops. The larger the range you want, the longer it takes.
I've been looking for a way to do it using only one call to Math.random().
This involves something like an easing function that pinches the value of Random() towards .5  basically what jonmack was talking about. Unfortunately, jonmack didn't provide the actual function, and that's the hard part.
Basically we're looking for a function that you pass Math.random() to (a value going from 01) and it pinches the value towards .5 This produces a graph that looks like this.
The following code is *close* to what I'm looking for, but it's not quite a bell curve. For large max (or a game, where accuracy isn't that important), it is far more efficient, however.
Code:
// take a value from 01 and 'pinch' it
// towards the middle (0.5)
function PinchRand(x)
{
return 0.5 + Math.pow(((Math.random().5)*2),7)/2;
}
// Does not produce a true bell curve distribution, but similar. Much more efficient than GaussRandom() for large 'max'
function GaussRandom2(max)
{
return Math.round(PinchRand()*max);
}
Here's a comparison of the two functions for a run of 10000. You'll see that GaussRandom2 is more likely to go to the edges, and has a higher spike in the middle. If you're using this for a game, it probably is sufficient, but if
you want true bellcurve statistics, it's way off.
Code:
(GaussRandom, followed by GaussRandom2)
0: 0, 80
1: 0, 178
2: 13, 221
3: 529, 339
4: 2456, 614
5: 4130, 7202
6: 2406, 586
7: 444, 296
8: 22, 214
9: 0, 200
10: 0, 70
 jim
Last edited by jbum; 03152004 at 06:25 PM.

Wow. It's far closer than anything I could muster and perfect for my application which is a game of sorts  a kind of dice roll probability thingy.
If you want to keep refining it be my guest, but you have given me two very viable options and I'm sure I could muck with it a bit more if I need more or less 'curviness'!
Thanks a ton.

Senior Member
Your dice comment gave me an idea. This one's pretty cheap, and it's a proper bell curve.
If you give it 10, it makes two 5sided dice, roll's up and adds the result.
// returns a value from 2 to max
//
function GaussRandomDice(max)
{
var sides = max/2;
return 2 +
Math.floor(Math.random()*sides) +
Math.floor(Math.random()*sides);
}

Senior Member
Your dice comment gave me an idea. This one's pretty cheap, cpuwise, and it's a proper bell curve.
If you give it 10, it makes two 5sided dice, roll's up and adds the result.
Code:
// returns a value from 2 to max
//
function GaussRandomDice(max)
{
var sides = max/2;
return 2 +
Math.floor(Math.random()*sides) +
Math.floor(Math.random()*sides);
}

The last algorithm is not really a bell curve. It is a linear "triangle".
We would assume that when the number of tests went large, ideally the random function is expected to distribute dice number with even chances.
For example, we have dice numbers of 0~5. For the first random function in the script, it returns equal chance of 0~5, and for each number 0~5, the second random function returns eaqual chance of hit for those number 0~5. So, the result of hit is something like this:
Code:
xxxxxx
xxxxxx
xxxxxx
xxxxxx
xxxxxx
xxxxxx

0123456789A  sum of hit
Thus, if the chance of sum up as '0' is C, the chance of sumup as '1' is 2*C and the chance of '2' should be 3*C........;
So, the result of sumup of 2 dice throwing does not distribute as a bell curve.

For the "falling leaf in the wind" algorithm, the equation seems to be something like y=K/(Maxx)!*(x)!; (I am not very sure about this, I just did a simple calculation only). I dont know whether this is a bell curve or not. Anyway, it looks more like "bell" curve than the dice algorithm.

The reason why it always return even number not odd number is that, we give the falling leaf only two options  forward or backward. That is 1 or 1; If we sum up 10 steps, we always get an even number. If we sum up 11 steps, we always get an odd number.
Here a question confused myself. Why dont we give it 3 options. Forward, backward and straight. That is 1,0,1. However, for what reason could we arbiturarily assume the chace of falling straight be the same as falling forward ? So, the algorithm confused myself.
Sorry, I could not give any answer.
Posting Permissions
 You may not post new threads
 You may not post replies
 You may not post attachments
 You may not edit your posts

Forum Rules

Click Here to Expand Forum to Full Width
