• home
  • forum
  • my
  • kt
  • download
  • Generating weighed random numbers in JavaScript

    Author: 2007-08-08 09:23:58 From:

    While it's impossible to forecast the exact occurrence of a random event, even a non-mathematician would agree we can manipulate the likelihood of something occurring. For example, in the case of winning the lottery, that would simply mean buying more tickets (and having your dreams dashed multiple times of course). In this tutorial, we take a stab at generating weighed random numbers, or random numbers with some more likely to show up than others. This is useful in situations where you need a more refined random engine, for example in a banner script that can display some banners more often than others. 

    Lets begin by looking back. As discussed in this tutorial, to generate a random number in JavaScript, the code:

    var randomnumber=Math.floor(Math.random()*11)

    will do nicely, whereby a random number between 0 to 10 is generated.

    Increasing the odds

    When we talk about manipulating the chances of a particular number popping up, first of all, it must be relative to some other numbers. This may seem obvious, but important to establish nevertheless. Even in the above example, there is an implied set of numbers, namely, 1 to 10, with the odds of each one getting picked being equal. Putting a weight on a number means changing this "equality."

    There are many techniques for generating weighed random numbers, and for an exhausted list, consult "Statistics meets Linear Algebra 808". For the rest of us, a very popular method is also a very simple one, which is what we'll look at here.

    What we need first is a set of random items to work with; instead of numbers, lets use something more meaningful, like fruits:

    var fruits=["Apples", "Oranges", "Grapes", "Bananas"]

    Now for the moment of truth. Since rarely do people like all fruits equally, we shall assign a weight to each fruit, using another literal array just for consistency:

    var fruitweight=[2, 3, 1, 4]

    There is nothing complicated about "fruitweight" at this point- it merely holds 4 numbers, each pertaining to their respective fruits above. However, it is these numbers we'll be using to signal the weight of each fruit. Considering they add up to 10, another way of looking at fruitweight is [20%, 30%, 10%, 40%].

    Now to the algorithm that connects the two arrays, and makes each fruit show up x percentage of the time as denoted by their weight divided by total weight. The basic idea is quite simple. We loop through array fruits[], and for each element (ie: Apples), put it into a new array the number of times its weight. For example, "Apples" has a weight of two, so we'll put it into the new array twice. The result is:

    var fruits=["Apples", "Oranges", "Grapes", "Bananas"]
    var fruitweight=[2, 3, 1, 4] //weight of each element above
    var totalweight=eval(fruitweight.join("+")) //get total weight (in this case, 10)
    var weighedfruits=new Array() //new array to hold "weighted" fruits
    var currentfruit=0
    
    while (currentfruit<fruits.length){ //step through each fruit[] element
    for (i=0; i<fruitweight[currentfruit]; i++)
    weighedfruits[weighedfruits.length]=fruits[currentfruit]
    currentfruit++
    }

    With all the loops running around, it may take a bit of starring before you realize what's going on. Basically we use an outer while loop to step through each of array fruit[]'s elements (4 steps in total), then for each element, populate the array weighedfruits[] with it the number of times the element's weight. So what have we accomplished? A lot, actually. The new array weighedfruits[] now contains duplicate copies of each of the original array's elements as laid out by their weight. A little thinking tells us this means the likelihood of each element getting randomly selected has also changed per its weight.

    We can proceed to displaying a random fruit- but with weight added in- by merely generating a random number within the bounds of the new array and using it as the index:

    var randomnumber=Math.floor(Math.random()*totalweight)
    document.write(weighedfruits[randomnumber])

    Viola! "Apples" should now show up roughly 20% of the time, Oranges 10%, and so on when the page is loaded.

    Conclusion

    The above algorithm can be used inside any of your random scripts that require "weight control." In fact, a similar technique is used not just in JavaScript, but many relevant Perl and PHP scripts.

    Have fun keeping tabs on your random scripts' weight!

    discuss this topic to forum

    relation tutorial

    No relevant information

    Category

      AJAX (20)
      Content Management (7)
      Cookies (4)
      Date and Time (12)
      Development (7)
      DHTML (14)
      Forms (8)
      Frequently Asked Questions (1)
      Image Display (9)
      Introduction to Javascript (5)
      Links and Buttons (4)
      Menus (2)
      Miscellaneous (5)
      Mouse Tricks (3)
      Navigation (8)
      Randomizing (4)
      Security (1)
      Text Effects (6)
      User Authentication (2)
      User Information (5)
      Windows and Frames (3)

    New

    Hot