GIDForums  

Go Back   GIDForums > Site Info and Feedback > GIDNetwork™
User Name
Password
Register FAQ Members List Calendar Search Today's Posts Mark Forums Read
 
 
Thread Tools Search this Thread Rate Thread
  #1  
Old 16-Jul-2005, 05:37
JdS's Avatar
JdS JdS is offline
Senior Member
 
Join Date: Aug 2001
Location: KUL, Malaysia
Posts: 3,370
JdS will become famous soon enough

Random / Probability / Weight formula?


I am trying to write a little script in PHP but this is not a question about code in particular. I am actually looking for a formula (or pseudocode) to help me get the following done.

I need one random ID (out of 2 possible unique IDs), 33% of the time for example. Out of the 2 unique IDs, one is the default ID and the other is supposed to be returned by the function just 33% of the time.

What I have so far is this:

Code:
// THE 2 IDs $id[0] = 76543; // default id $id[1] = 65497; // this id is supposed to be returned just 33 percent of the time. $weight = 33; // i.e. 33 percent of the time. // A RANDOM INTEGER BETWEEN 1 AND 100 $random = random100(); // SET THE DEFAULT ID AS THE RETURN VALUE $uid = $id[0]; // TEST THE RANDOM INTEGER TO SEE IF IT'S LESS THAN / EQUAL TO $WEIGHT if( $random <= $weight ) $uid = $id[1]; // $uid is reset to this weighted id instead. // DONE return $uid;

I know this would work but I wonder if there is a better suggestion?
__________________
J de Silva

GIDApp | GIDBlog | GIDForums | GIDNetwork | Learning Journal
  #2  
Old 16-Jul-2005, 08:47
cable_guy_67's Avatar
cable_guy_67 cable_guy_67 is offline
Senior Member
 
Join Date: Oct 2004
Location: Florina, Greece
Posts: 1,112
cable_guy_67 is a jewel in the roughcable_guy_67 is a jewel in the roughcable_guy_67 is a jewel in the roughcable_guy_67 is a jewel in the rough
Since you seem to be doing this test against a particular uid and want to know if it or the default should be shown why not do something like:
Code:
(uid type) ChooseUID( (uid type) U, int weight){ // generate your random # between 1 and 100 random_num = real_random(100); // once you have your decidedly random number... if (random_num <= weight){ return U; }else return 76543 // default uid; }

This way, you could control the weight and use it for any check of a UID by calling as:
Code:
show_UID = ChooseUID( 65497, 33 ); // or show_UID = ChooseUID( uid[x], 33 );
If the sent uid wins it gets returned, if not the default gets returned. Either way, you should have a valid UID in show_UID. This would also be good if the sent uid is already stored, just send the variable $uid[#] for the first argument. If uid[#] is globally known just replace the variable names with the uid array item you want to use of course.

I guess so long as you have a real random number generator this should work just fine. An example of this (in c++) can be found here.

Mark
__________________

"A happy person is not a person in a certain set of circumstances, but rather a person with a certain set of attitudes."
--Hugh Downs

Stories from the NICU Blog
  #3  
Old 16-Jul-2005, 09:15
JdS's Avatar
JdS JdS is offline
Senior Member
 
Join Date: Aug 2001
Location: KUL, Malaysia
Posts: 3,370
JdS will become famous soon enough
Thank you Mark, although it seems you missed my whole point of starting this thread.

I am not looking to "clean up" the code in my example, I actually have it the way you suggested already. I expanded it earlier in my example to make my situation clearer. The original code I wrote is like this:

PHP Code:

/**
 *    @param    string    $did    Default ID
 *    @param    string    $aid    Alternate ID
 *    @param    integer    $weight    Weight
 *
 *    @return    string    AdSense Publisher ID
 */
function _adsense_get_publisher_id( $did, $aid, $weight )
{
    $random = mt_rand( 1, 100 );
    if( $random <= $weight )
        $did = $aid;
    return( $did );
} 



So you see, it's almost identical to what you suggested.

What I was wondering is IF there is a better, more smarter way to do what is it that I am trying to do.
__________________
J de Silva

GIDApp | GIDBlog | GIDForums | GIDNetwork | Learning Journal
  #4  
Old 17-Jul-2005, 21:49
cable_guy_67's Avatar
cable_guy_67 cable_guy_67 is offline
Senior Member
 
Join Date: Oct 2004
Location: Florina, Greece
Posts: 1,112
cable_guy_67 is a jewel in the roughcable_guy_67 is a jewel in the roughcable_guy_67 is a jewel in the roughcable_guy_67 is a jewel in the rough
Quote:
Originally Posted by JdS
So you see, it's almost identical to what you suggested.

What I was wondering is IF there is a better, more smarter way to do what is it that I am trying to do.

OK, a good night's sleep in me and perhaps I can come up with a better (I don't know if it's smarter or smart-alec though) way to do what you are talking about.

It doesn't suprise me we came up with nearly identical initial solutions. It seems to jump out at you as an easy way to handle things, but actually is incorrect for this use. Once I came to grips with that, I realized that a weighted list is really what you need. Our initial suggestions were not a weighted percentile, but a kind of lottery. To get a truly weighted split you will need a play list which is an array of pubID array indexes. For this example, I will assume that is the real goal here. To reach that goal I will attack it in stages. The code will be c++ but from a cursory scan of a php help file it looks like the conversion should be simple enough. The whole thing could even be wrapped into a class and reduce the need for most of the arguments in the posted functions. I'm barely a c++ guy so if someone wants to port my code to php knock yourself out. I'm fairly sure I could make the conversion, but most likely it would take a bit of time and a lot of reading.

TASK A : Get the Default AdSense pub ID. Since the actual connection is for the particular WebMaster to implement, I have simulated that with an array of pubisher ID's to be used. When additional runtime information is needed it will be gotten from the console. I have seperated those times into small functions that can be replaced with the proper php way.

TASK B : Get the percentage of the default and the number of additional publishers to be evenly weighted. Once again, something that will be internalized by the implementer.

TASK C : Figure out how large the set will need to be to give a true, weighted array. This array can be used to push to a stack that could then be poped when you need the next ASpubID. When you get to the end just build another and start the process over.

TASK D : Build the random play list. It will use the ASpubID[] array to get the proper ID. The array itself it will just be a lookup for ASpubID's. For example,

CPP / C++ / C Code:
// default_pub will always be at the '0' index
// this example uses 10% for default and 8 additional pubID's
// that will be evenly weighted.

unsigned ASpubID[9] = { 111, 222, 333, 444, 555, 666, 777, 888, 999 };

// when the random lookup array is built, it's info will refer to this array.
// EX. rnd_array = { 0, 2, 8, 8, 5, 2, 0, 3, 4, 4, ... }

The below code should give an example. Feel free to ask questions.
CPP / C++ / C Code:
// copyright (C) 2005 Mark Roth Nescopeck PA
// No warrenty, no nothing.  If you don't like it don't run it.

#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>
using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::getline;
using std::atoi;

static bool seeded = false;

const unsigned GetPer100(const unsigned DefPercent, const unsigned OtherIDs){
  // gets a count less than or equal to 100.  It is the per/100 number
  const unsigned per100units = DefPercent + (((100-DefPercent)/OtherIDs)*OtherIDs);
  return per100units;
}


const unsigned GetMagic100(const unsigned Per100units, const unsigned OtherID){
  // gets the number that will set the size of the random index array
  unsigned magic100;
  const unsigned per100remain = 100 - Per100units;

  for(magic100 = 1; ((per100remain * magic100) % OtherID) != 0; magic100++);
  return magic100;
}


void RNDseed(){
  // a one shot random seed
  srand(time(NULL));
  seeded = true;
}


const unsigned RNDgen(const int MAX) {
  // a simple random number generator
  // returns a number from 0 to MAX-1
  return (rand() % MAX);
}


void BuildRndList( unsigned array[], const unsigned size,
                   const unsigned OtherIDs, const unsigned OtherIDamt ){
  // does the work of building the weighted list
  if (seeded == false) RNDseed();
  // set array to all '0'
  for ( unsigned i = 0; i < size; i++ ) array[i] = 0;
  for ( unsigned i = 1; i <= OtherIDs; i++) {
    for (unsigned j = 0; j < OtherIDamt; j++) {
      bool loop = true;
      do{
        const unsigned RNDnum = RNDgen(size);
        if ( array[RNDnum] == 0 ) {
          array[RNDnum] = i;
          loop = false;
        }
      }while ( loop );
    }
  }
}

const unsigned GetUnsigned(const string text, unsigned hi, unsigned low){
  // returns an number within a given range
  string buf;
  unsigned atoi_buf;

  do{

    cout << "Enter " << text << " : ";
    getline(cin, buf);
    atoi_buf = atoi(buf.c_str());

  }while ( (atoi_buf > hi) || (atoi_buf < low) );

  return atoi_buf;
}


int main(){

  string buffer;
  
  do{
    unsigned magic_number;

    const unsigned defID = GetUnsigned("DefID percentage ", 100, 0);
    const unsigned otherIDs = GetUnsigned("OtherID number   ", 50, 1);
    const unsigned per100units = GetPer100( defID, otherIDs);
    unsigned ASpubID[1 + otherIDs];

    for ( unsigned i = 0; i < (otherIDs + 1); i++ ) ASpubID[i] = 100 + i;

    magic_number = GetMagic100(per100units, otherIDs);
    const unsigned array_size = magic_number * 100;
    cout << "units per 100 unused = " << 100 - per100units << endl;
    cout << "array_size = " << array_size << endl << endl;
    unsigned rndASpubID[array_size];
    const unsigned otherIDamt = (array_size - (defID * magic_number)) / otherIDs;
    
    BuildRndList( rndASpubID, array_size, otherIDs, otherIDamt );
    
    // at this point the array rndASpubID has a list of publisher indexes
    // that can be used by a stack system to actually access the proper
    // ID.  Everything below is just for testing and display.

    unsigned counter[51];
    for ( unsigned i = 0; i <= 51; i++ ) counter[i] = 0;
    for ( unsigned i = 0; i < array_size; i++) {
      cout << ASpubID[rndASpubID[i]] << "  ";
      counter[rndASpubID[i]]++;
    }
    cout << endl;
    for ( unsigned i = 0; i < (otherIDs + 1); i++ ) {
      cout << endl << "number of " << ASpubID[i] << "'s = " << counter[i] << endl;
    }
    cout << endl;

    cout << "try another combo (y/n) : ";
    getline(cin, buffer);
  }while (buffer == "y");

  return 0;
}

Ok, this will give you an array with randomly placed weighted indexes that match up with the publisher id's. There are some testing outputs etc. The documentation is relatively poor but since the bulk of the code is for testing and running from a console the actual code is relatively small. Attached is a zip of the program built for windows, stripped and upx'ed.

Mark
Attached Files
File Type: zip ArraySize.zip (79.2 KB, 39 views)
__________________

"A happy person is not a person in a certain set of circumstances, but rather a person with a certain set of attitudes."
--Hugh Downs

Stories from the NICU Blog
  #5  
Old 20-Jul-2005, 08:54
JdS's Avatar
JdS JdS is offline
Senior Member
 
Join Date: Aug 2001
Location: KUL, Malaysia
Posts: 3,370
JdS will become famous soon enough
Thank you Mark. I ran the little program you attached in your last reply. I will be replying to this thread when I ready to ask you specific questions about what some of the functions (in your example) do.

I just wish you knew something about PHP, so you can help me extend it.
__________________
J de Silva

GIDApp | GIDBlog | GIDForums | GIDNetwork | Learning Journal
  #6  
Old 26-Aug-2005, 23:08
WaltP's Avatar
WaltP WaltP is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Midwest US
Posts: 3,435
WaltP is a name known to allWaltP is a name known to allWaltP is a name known to allWaltP is a name known to allWaltP is a name known to allWaltP is a name known to all
Hey, just thought of one. It's in psuedo code, cuz I don't want to look up the PHP syntax at the moment:
Code:
i = random(3) ; return a random value from 0 thru 2 i = i mod 2 ; Even or odd? if (i = 0) return 76543 ; return default else return 65497 ; return other
or more simply
Code:
id[2] = {76543,65497} return (id[random(3) mod 2])
__________________

Definition: Politics
Latin, from
poly meaning many and
tics meaning blood sucking parasites
-- Tom Smothers
 


Thread Tools Search this Thread
Search this Thread:

Advanced Search
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Help with random numbers da_bomb50 MySQL / PHP Forum 3 04-Aug-2004 19:34
Assigning random values enggwaqas C++ Forum 3 22-Jun-2004 10:43
Need a script for selecting random tabels and from those tabels selecting random ques mlt MySQL / PHP Forum 2 12-Sep-2003 09:01
Random no longer JUST random... JdS GIDTopsites™ 0 12-Jan-2003 09:57

Network Sites: GIDNetwork · GIDApp · GIDBlog · Learning Journal by J de Silva, The

All times are GMT -6. The time now is 22:22.


vBulletin, Copyright © 2000 - 2017, Jelsoft Enterprises Ltd.