A Flash Developer Resource Site

Results 1 to 6 of 6

Thread: Generating Random Numbers from Normal(Gaussian) Distribution

  1. #1
    Member
    Join Date
    Oct 2003
    Location
    Cincinnati, OH, USA
    Posts
    44

    Generating Random Numbers from Normal(Gaussian) Distribution

    We are in the process of builing a statistics simulation for a client. One of the requirements of the simulation is to first generate a set of 1000 random numbers from a Normal (or Guassian) distribution.

    Does ActionScript have the builty in functionality to generate random numbers from anything other than a Uniform distribution?

    If this functionality is not built in, does anyone know of a component or pre-built script that can provide this functionality?

    How hard would it be, if either of the two options above are not possible, to generate random numbers from a Normal(Guassian) distribuion using ActionScript?

    Thanks in advance for any help!!!

    Aaron

  2. #2
    Senior Member jbum's Avatar
    Join Date
    Feb 2004
    Location
    Los Angeles
    Posts
    2,920
    There is no built-in mechanism, but since actionscript is a programming language, it's not hard to put stuff like this together.

    The Central Limit Theorem says that the mean of any set of variates with any distribution having a finite mean and variance tends to the normal distribution.

    This suggests that if we produce a number of random numbers using Math.random() or random() which are all in the same range, and average them, the resulting numbers will exhibit normal distribution.

    A very simple example of this is a pair of dice - a single die produces a number with flat distribution, but the pair exhibits something approaching normal distribution (with 7, the number in the middle of the range, being the most common).

    We can reproduce this effect by producing some random numbers and averaging them, like so:

    code:

    a = random(MaxRange+1);
    b = random(MaxRange+1);
    c = random(MaxRange+1);
    d = random(MaxRange+1);

    r = Math.round((a+b+c+d)/4);
    // take the average - this is our random number
    // with normal distribution




    Here is a complete script I just wrote (paste this into a new movie and set the frame-rate to 30 fps) that uses the above technique. It counts the number of hits and displays a bar chart that eventually looks like a bell curve.

    See the movie here.

    code:


    // Bell Curve Sample

    sumHits = [];
    MaxRange = 30; // Number of random slots
    Margin = 50;
    BarWidth = (Stage.width-Margin*2) / MaxRange;
    GraphBase = Stage.height-55;
    GraphHeight = Stage.height-100;
    maxHits = 1;

    for (i = 0; i <= MaxRange; ++i)
    {
    sumHits[i] = 0;
    _root.createTextField('txt_'+i, 10+i,
    Margin+i*BarWidth, GraphBase+10+(i%4)*10, 20, 20);
    }

    onEnterFrame = function()
    {
    a = random(MaxRange+1);
    b = random(MaxRange+1);
    c = random(MaxRange+1);
    d = random(MaxRange+1);

    // take the average - this is our random
    r = Math.round((a+b+c+d)/4);

    sumHits[r]++;
    if (sumHits[r] > maxHits)
    maxHits = sumHits[r];
    this.clear();
    this.lineStyle(4, 0xFF0000, 100);
    for (x = 0; x <= MaxRange; ++x)
    {
    this.moveTo(x*BarWidth+Margin, GraphBase);
    this.lineTo(x*BarWidth+Margin, GraphBase-sumHits[x]*GraphHeight/maxHits);
    _root["txt_"+x].text = sumHits[x];
    }
    }


    Last edited by jbum; 07-30-2004 at 02:40 PM.

  3. #3
    Member
    Join Date
    Oct 2003
    Location
    Cincinnati, OH, USA
    Posts
    44
    jbum,
    Thank you so much for the quick reply. The code that you provided will serve as a great basis by which to start developing this simulation. I also very much appreciate the explanation of the theory behind the code, it refreshed my memory of all the Statistics classes I took in college and helped me better understand the task at hand!

    Thanks again for you help. It is nice to know that there are people out there like yourself that are willing to help the community!

    Aaron

  4. #4
    Member
    Join Date
    Oct 2003
    Location
    Cincinnati, OH, USA
    Posts
    44
    Well, here I am a couple of months later, with more requests for advice. The original code posted on this thread helped me greatly with creating the simulation that I needed to make. Now I am pushing it a little further and have run into a road block.

    Here is the link to the current version of my simulation:
    http://www.wayspire.com/playground/B...BellCurve3.swf

    My problem lies in the third graph(on the bottom), which plots the cumulative mean of all samples drawn from the population. The point is to show how the cumulative average starts off all over the place, but as more samples are drawn, converges towards the mean of the population.

    The problem here is scaling. The graph works fine, but it is hard to see the intracacies of the line. What I would like to do is scale the plots to the vertical height of the graph. For example, the height of the graph is 215px. However, I am only generating plots between 13 and 17. What I would essentially like to to is make 13 the bottom of the graph, and 17 the top.

    For example:
    Code:
    17 |
       |\
       | \  /\---
       |  \/
    13 |_________
    The problem, as you can see from the SWF, is that the graph is not scaling, and is instead scrunched up at the top of the graph...

    Code:
    17 |\/\/------
       |
       |
       |
    13 |_________
    Here is the code:
    Code:
    if (_root.StdDev > _root.Mean/2) {
       var MaxRange = 2 * _root.Mean + 2*(_root.StdDev-(_root.Mean/2));
    } else {
       var MaxRange = 2 * _root.Mean;
    }
    	
    var GraphWidth = 215;
    var GraphHeight = 165;
    var GraphBase = GraphHeight-1;
    
    var minMean = 215;
    var maxMean = 1;
    for (i = 0; i <= Count; i++) {
       if (_root.CumulativeMeanHits[i] > maxMean) {
          maxMean = _root.CumulativeMeanHits[i];
       } else if (_root.CumulativeMeanHits[i] < minMean) {
          minMean = _root.CumulativeMeanHits[i];
       }
    }
    
    _root.CumulativeGraph.clear();
    _root.CumulativeGraph.lineStyle(1, 0x000000);
    _root.CumulativeGraph.moveTo(0, _root.GraphBase);
    for (x = 0; x <= Count; x++) {
       with(_root.CumulativeGraph) {
          lineTo(x*(GraphWidth/Samples), _root.GraphBase-(_root.CumulativeMeanHits[x]*(_root.GraphHeight/maxMean)));
       }
    }
    Any ideas on how to make this scale the way I would like it to?

    Thanks in advance!
    Aaron

  5. #5
    Junior Member
    Join Date
    Apr 2009
    Posts
    1
    The Marsaglia transform is a more robust solution:
    http://blog.controul.com/2009/04/sta...bution-in-as3/

  6. #6
    Junior Member
    Join Date
    Mar 2012
    Posts
    2
    Quote Originally Posted by jbum View Post

    The Central Limit Theorem suggests that if we produce a number of random numbers using Math.random() or random() which are all in the same range, and average them, the resulting numbers will exhibit normal distribution.

    We can reproduce this effect by producing some random numbers and averaging them, like so:

    [as]
    a = random(MaxRange+1);
    b = random(MaxRange+1);
    c = random(MaxRange+1);
    d = random(MaxRange+1);

    r = Math.round((a+b+c+d)/4);
    // take the average - this is our random number
    // with normal distribution
    erm, if i have the number of range from 3 to 200, so i write loop for 198 time for uniform distribution, then only get the average of them as r (normally distribution rite???)

    but, if now i want is log normal distribution, may i just
    y = Log(r)

    then, y is log normal distribution????

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  




Click Here to Expand Forum to Full Width

HTML5 Development Center