Page 1 of 2

Randomising a no. between 0 and 100.....

Posted: Fri Jan 03, 2003 11:46 am
by megaming
Ok, I have found half of the answer here: http://www.devnetwork.net/forums/viewtopic.php?t=4906

So at the moment, I have:

Code: Select all

<?php 
   // define re-mapping function 
   function remap($floatNumber) &#123; 
      return pow($floatNumber,2) ; 
   &#125; 

   // get a random number between 0 and 1 
   $randval = mt_rand() / mt_getrandmax() ; 
   // apply the remapping function 
   $skewrandval = remap($randval) ; 
   // make the new number fit in the original range 
   $skewrandval = $skewrandval * (100 - 1) + 1; 
   // you can make the result an integer now 
   $finalrandval = floor($skewrandval) ; 
?>
The thing is, I need it to be affected by $var which has a value between 1 and 250.

So if $var is 250, $finalrandval is pretty likely to be higher than if $var was 1.

Anyone know how to do this? I hope you understand what I mean...

Thanks :D

Posted: Fri Jan 03, 2003 12:58 pm
by hob_goblin
try this, i dont know if it will work, but its worth a try:

Code: Select all

<?php 
   // define re-mapping function 
   function remap($floatNumber) &#123; 
      return pow($floatNumber,2) ; 
   &#125; 


   $var = 250; // Upper boundry


   // get a random number between 0 and 1 
   $randval = mt_rand() / mt_getrandmax() ; 
   // apply the remapping function 
   $skewrandval = remap($randval) ; 
   // make the new number fit in the original range 
   $skewrandval = $skewrandval * ($var - 1) + 1; 
   // you can make the result an integer now 
   $finalrandval = floor($skewrandval) ; 
?>

Posted: Fri Jan 03, 2003 1:01 pm
by megaming
no, thats not what I meant :(

Posted: Fri Jan 03, 2003 3:58 pm
by hob_goblin
maybe this?

Code: Select all

<?php 

   assist_val($variable)&#123;
   $foo = $variable / 250;
   $rand = mt_rand() / mt_getrandmax();
   $bar = $foo * rand;
   return floor($bar);
   &#125;


   $var = 250;

   echo assist_val($var);

?>

Posted: Fri Jan 03, 2003 4:04 pm
by megaming
i'm getting a parse error on line 3 of that code :(

Posted: Fri Jan 03, 2003 5:11 pm
by hob_goblin
Oh, woops, typo:

[edit]

doesn't work anyways... i dont know, this is hard, i'll think of something

[/edit]

Posted: Fri Jan 03, 2003 8:44 pm
by Rob the R
Like the earlier post you referenced mentioned, you can tweak the second argument of the pow function to skew less or more. IN this case, a number lower than one will skew toward the higher numbers. You could therefore pass $var to the remap() function to do something like this:

Code: Select all

<?php
   // define re-mapping function 
   function remap($floatNumber,$skewfactor) { 
      // assume $skewfactor is between 1 and 250
      // we want the minimum $exponent value to be 1/25,
      // which will skew toward the high values quite a lot.
      // The "10" value below can be increased if the skew
      //  is too severe.
      $exponent = 10 / $skewfactor ;
      // make sure we don't have any positive exponents
      // (which would remap values toward the low numbers)
      if ($exponent > 1) {
         $exponent = 1 ;
      }
      return pow($floatNumber,$skewfactor) ; 
   } 

   // get a random number between 0 and 1 
   $randval = mt_rand() / mt_getrandmax() ; 
   // apply the remapping function 
   $skewrandval = remap($randval,$var) ; 
   // make the new number fit in the original range 
   $skewrandval = $skewrandval * (100 - 1) + 1; 
   // you can make the result an integer now 
   $finalrandval = floor($skewrandval) ; 
?>
You should still experiment to see how skewed your results are for different values of $var. A $var of 250 might produce way too much skew toward the high numbers; if so, just increase the "10" in the remap() function.

Posted: Sat Jan 04, 2003 3:37 am
by megaming
Rob, thats great, but the $finalrandval is always 1....

Posted: Sat Jan 04, 2003 5:59 am
by Rob the R
Well, perhaps the "10" should be changed. Try changing it to "100" and see what happens.

Posted: Sat Jan 04, 2003 6:05 am
by megaming
I'm still getting 1 every time :(

I tried it on 1000 too....

Posted: Sat Jan 04, 2003 6:30 am
by Elmseeker
Hmmm...$exponent is defined as 10 divided by the $skewfactor and then reset to 1 if it's larger than 1...so $exponent is always .(something) or 1. Not sure if this is affcting the output or not but I am just wondering why it is being done this way?

Code: Select all

<?php
      $exponent = 10 / $skewfactor ; 
      // make sure we don't have any positive exponents 
      // (which would remap values toward the low numbers) 
      if ($exponent > 1) { 
         $exponent = 1 ; 
      } 
?>

Posted: Mon Jan 06, 2003 10:31 pm
by Rob the R
OK. I have it. Try this:

Code: Select all

<?php
   function remap($floatnumber,$skewfactor) {
      // when $skewfactor is 1, we want the $exponent to be 1 (no skew)
      // when $skewfactor is 250 (maximum), we want $skewfactor
      // to be 0.1 (heavily skewed to larger numbers)
      // create a linear function to determine $exponent
      $exponent = (((0.1 - 1) / (250 - 1)) * $skewfactor) +
         (1 + ((1 - 0.1) / (250 - 1)))  ;
      // the second argument to "pow" is the key: values greater
      // than 1 remaps preferentially to smaller numbers, values
      // between 0 and 1 remaps to larger numbers.
      return pow($floatnumber,$exponent) ;
   }

   function get_random($var) {
      // get a random number between 0 and 1
      $randval = mt_rand() / mt_getrandmax() ;
      // apply the remapping function
      $skewrandval = remap($randval,$var) ;
      // make the new number fit the original range
      $skewrandval = $skewrandval * (100 - 1) + 1 ;
      // you can make the result an integer now
      $finalrandval = floor($skewrandval) ;
      return $finalrandval ;
   }
?>
My main problem before was I forgot to change the "pow" function - the second argument should have been "$exponent".

I tested this code by generating 1000 random numbers for each value of $var and averaged the results. It looks to be pretty smooth:
$var = 1, Average: 49.842
$var = 50, Average: 53.968
$var = 100, Average: 61.596
$var = 150, Average: 68.35
$var = 200, Average: 78.58
$var = 250, Average: 89.938

Based on the math, I would expect to not see any holes in the random numbers (that is, this does not just get a random number and add 20 to it so that you never get any numbers below 20), but I did not test to that degree.

Elmseeker,
I used the code you pointed out to make sure I never got an $exponent value greater than 1, since that would actually skew the results to smaller numbers. It was kludgy, though, so I've made the calculation of $exponent more precise in the above code.

Posted: Tue Jan 07, 2003 12:05 am
by Elmseeker
Ahhh, yes, thank you. IMHO the new way makes a bit more sense...I can at least understand what it does by looking at it now anyway lol...Thanks again, appreciate the explanation. :)

Posted: Tue Jan 07, 2003 9:33 am
by megaming
cool!

Thanks for dedicating so much time to this everyone (rob especially)!

I can finally get my script working now :D

Math Problem

Posted: Thu Apr 15, 2004 9:57 pm
by S_henry
I want to display 12345.6789 as 1.23456789e+4. Anybody knows what function in PHP I should use?