PDA

View Full Version : Random money amounts (big numbers)



Floydian
09-01-2008, 08:02 PM
A lot of times, I see code that is designed to randomly choose an amount of money to give a user programmed like this:



$min = 100;
$max = 200;
$amount = rand($min, $max);


This pattern arises when you have min and max values stored in a database table like crimes perhaps. But this could apply to lots of things, even things that aren't money related.

The problem arises when the amounts get into the billion range. At about 2.1 billion, rand starts to spit out negative numbers. PHP's rand function is based on integers which is in contrast to say javascript or mysqls float based rand functions.


Because of this, that code pattern will break down with large numbers. How do we compensate?



function range_to_value($low, $high, $percent) {
$range = $high - $low;
$target = $range * $percent * 0.01 + $low;
return $target;
}


This is a nifty little function that I use that has saved me time programming many a script...
All it does is takes a min and max value, and then computes a value in the middle of that according to the percent passed into the function.


Instead of just figuring out the percent of the max value, the range begins at the min value and ends at the max value. Simply doing something like 200 * 0.5 (fifty percent of 200) results in 100, but suppose we want 50% in the middle of 100 and 200.

Well, the answer is 150, and the way to do it is:


function range_to_value($low, $high, $percent) {
$range = $high - $low;
$target = $range * $percent * 0.01 + $low;
return $target;
}
$min = 100;
$max = 200;
$amount = range_to_value($min, $max, rand(1,100));


Now, I've set that up to generate a random percent, but that third parameter could be set to 50.

Have fun with this! It will work with extremely large numbers. The only limitation is that the range, in this case a range of 100 numbers, is 100.

If your range is 1bill to 2 bill, the range would be 1bill, but with this code, you only get 100 variations. So be that as it may, you still get results spread out over that range, but there are only ever going to be 100 different results.

XCU53S
09-01-2008, 08:38 PM
Ive been using something similar for a while now but your method is better

POG1
09-01-2008, 08:47 PM
The problem arises when the amounts get into the billion range. At about 2.1 billion, rand starts to spit out negative numbers. PHP's rand function is based on integers which is in contrast to say javascript or mysqls float based rand functions.


I could be wrong but isn't the limit to an integer 2.1 billion anyway?

Floydian
09-01-2008, 08:58 PM
Thanks for the compliment Jaye1 ;)


EDIT: range_to_percent is dependent on another function which I didn't originally post, It's now posted along with the other function.


You might like the companion function of the range_to_value() function. It does the opposite which is takes a min and max value, and a percent. Then it returns the actual value in the range.

For instance, range_to_percent(100, 200, 150) would give you a percent that represents where in the middle of the range from 100 to 200 that the number 150 is.

Which is 50%.




function to_percent($min, $max) {
return $percent = $min * 100 / $max;
}


// submit a numeric value, and find a percent of where in the range that number is.
function range_to_percent($low, $high, $value) {
$range = $high - $low;
$target = to_percent($value - $low, $range);
return $target;
}



Sometimes I use these two range functions in combination. Say in your crime file you want to base pay out on stats.

Suppose your crime exp is 500 and you want to base pay on crime exp. A min crime exp of 400 and a max crime exp of 1000.

You would get a % of where in the middle your crime exp is in the range of 400 to 1000.

And then you might have a min payout of 100 bucks and a max payout of 300 bucks. If your crime exp was at 400, you'd get 100 bucks, and if your crime exp was at or above 1000, you'd get 300 bucks.
Please note that the range to percent function will return %'s less than 0 and greater than 100, so you might want to have an if block to compensate. I'll demonstrate:



$stat_percent = range_to_percent(400, 1000, 500);

if ($stat_percent < 1) { $stat_percent = 1; }
elseif ($stat_percent > 100) { $stat_percent = 100; }
$payout = range_to_value(100, 300, $stat_percent);



And now you have a sweet, easy to code, sliding payout scale where you have min and max stat values and min and max payout values, and your payouts would be scaled to the payout.

If you wanted to actually randomize the result, you could then do:


$payout *= rand(50,100) * 0.01;

That would make the final payout somewhere in the range of 50% to 100% of whatever they would have gotten.

Alternatively, you could modify the percentage you ended up with, i.e., "$stat_percent" like this:




$stat_percent = range_to_percent(400, 1000, 500);

if ($stat_percent < 1) { $stat_percent = 1; }
elseif ($stat_percent > 100) { $stat_percent = 100; }

$stat_percent = range_to_percent($stat_percent*0.5, $stat_percent, rand(1,100));

$payout = range_to_value(100, 300, $stat_percent);




This line here: $stat_percent = range_to_percent($stat_percent*0.5, $stat_percent, rand(1,100));

would take your percentage, and then come up with a randomized percentage somewhere in the range of:
the half of that percentage and the full percentage.

So, if your percentage had been 75, you would get a random percentage from 37.5 to 75.

Of course that could be tightened up so that the randomized amount wouldn't swing as much as that would. Say instead of having a range that swings by 50%, you could do $stat_percent*0.9 which would give you a random swing in the 10% range.

Anonymous
09-01-2008, 09:00 PM
I could be wrong but isn't the limit to an integer 2.1 billion anyway?

Depends on your OS, how you manipulate the numbers and how you store/retrieve them.

Floydian
09-01-2008, 09:01 PM
The problem arises when the amounts get into the billion range. At about 2.1 billion, rand starts to spit out negative numbers. PHP's rand function is based on integers which is in contrast to say javascript or mysqls float based rand functions.


I could be wrong but isn't the limit to an integer 2.1 billion anyway?



That's right. The idea here is that instead of putting numbers larger than 2.1 billion into the rand function, we put smaller numbers into it, i.e., 1 to 100, and then calculate a money amount.

A random number of say 34 would amount to 34% of something. If you wanted a min and max range of money values, then 34% into that range is calculated with my range_to_value() function instead of using rand(min, max) which would fail with large numbers.

Joel
09-01-2008, 11:37 PM
Very Nice Floydian

Haunted Dawg
09-02-2008, 01:17 AM
Floydian in your first post your missing a )



function range_to_value($low, $high, $percent) {
$range = $high - $low;
$target = $range * $percent * 0.01 + $low;
return $target;
}
$min = 100;
$max = 200;
$amount = range_to_value($min, $max, rand(1,100));

Floydian
09-02-2008, 02:19 AM
Thanks for the compliments Extermination ;)

Thanks for the correction killah :mrgreen:

Haunted Dawg
09-02-2008, 02:28 AM
My eye is very cachy :P